From ba71ca11cac9d2800fe682ff777d49b38ad0afff Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Mon, 11 Dec 2023 10:32:46 +0100 Subject: [PATCH 01/54] feat: symfony 7 support - makes doctrine/annotations optional - updates tests and ci to test with both symfony 7 and < symfony 7 version - adds routes-attributes.yaml file for symfony 7 compatible controllers/routes - skips tests/packages related to packages like jms serializer, bazinga, etc not supported by symfony 7 for symfony 7 matrix --- .github/workflows/continuous-integration.yml | 8 + Command/DumpCommand.php | 5 +- .../Compiler/ConfigurationPass.php | 3 +- DependencyInjection/NelmioApiDocExtension.php | 7 +- Describer/OpenApiPhpDescriber.php | 25 +- .../Annotations/AnnotationsReader.php | 8 +- .../Annotations/OpenApiAnnotationsReader.php | 19 +- .../SymfonyConstraintAnnotationReader.php | 14 +- ModelDescriber/FormModelDescriber.php | 7 +- ModelDescriber/JMSModelDescriber.php | 5 +- ModelDescriber/ObjectModelDescriber.php | 4 +- Resources/config/fos_rest.xml | 2 +- Resources/config/services.xml | 2 +- RouteDescriber/FosRestDescriber.php | 8 +- Routing/FilteredRouteCollectionBuilder.php | 11 +- Tests/Functional/BazingaFunctionalTest.php | 5 + Tests/Functional/Controller/ApiController.php | 7 +- .../Functional/Controller/ApiController81.php | 2 +- .../Controller/ClassApiController.php | 35 +- .../Controller/InvokableController.php | 42 +- .../Controller/SerializedNameController.php | 48 +- .../Functional/Controller/TestController.php | 38 +- .../Controller/UndocumentedController.php | 37 +- Tests/Functional/Entity/Article.php | 34 +- .../Entity/EntityWithAlternateType.php | 46 +- .../Entity/EntityWithNullableSchemaSet.php | 129 +++-- .../Entity/EntityWithObjectType.php | 28 +- Tests/Functional/Entity/EntityWithRef.php | 27 +- .../Functional/Entity/SymfonyConstraints.php | 534 ++++++++++++------ ...SymfonyConstraintsWithValidationGroups.php | 79 ++- .../Entity/SymfonyDiscriminator.php | 35 +- Tests/Functional/Entity/User.php | 388 +++++++++---- .../Symfony7/SerializedNameEntity.php | 34 ++ Tests/Functional/FOSRestTest.php | 5 + Tests/Functional/FunctionalTest.php | 6 +- .../Resources/routes-attributes.yaml | 40 ++ Tests/Functional/TestKernel.php | 191 ++++--- .../Annotations/AnnotationReaderTest.php | 6 +- .../Fixture/CompoundValidationRule.php | 1 + .../SymfonyConstraintAnnotationReaderTest.php | 40 +- Tests/RouteDescriber/FosRestDescriberTest.php | 16 +- .../FilteredRouteCollectionBuilderTest.php | 48 +- composer.json | 43 +- 43 files changed, 1402 insertions(+), 670 deletions(-) create mode 100644 Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php create mode 100644 Tests/Functional/Resources/routes-attributes.yaml diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index ac6c48f14..514297e40 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -34,6 +34,8 @@ jobs: symfony-require: "5.4.*" - php-version: 8.1 symfony-require: "6.3.*" + - php-version: 8.2 + symfony-require: "7.0.*" steps: - name: "Checkout" @@ -59,6 +61,11 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- + - name: Remove packages not compatible symfony 7 + if: matrix.symfony-require == '7.0' + run: | + composer remove friendsofsymfony/rest-bundle sensio/framework-extra-bundle jms/serializer-bundle willdurand/hateoas-bundle --no-update --dev + - name: "Install dependencies with composer" env: SYMFONY_REQUIRE: "${{ matrix.symfony-require }}" @@ -66,6 +73,7 @@ jobs: composer global config --no-plugins allow-plugins.symfony/flex true composer global require --no-progress --no-scripts --no-plugins symfony/flex composer update --no-interaction --no-progress ${{ matrix.composer-flags }} + composer update --no-interaction --no-progress ${{ matrix.composer-flags }} - name: PHPUnit Tests run: vendor/bin/simple-phpunit --configuration phpunit.xml.dist --coverage-text diff --git a/Command/DumpCommand.php b/Command/DumpCommand.php index 3fa9d7ab4..29c78968f 100644 --- a/Command/DumpCommand.php +++ b/Command/DumpCommand.php @@ -62,10 +62,7 @@ protected function configure(): void ; } - /** - * @return int|void - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $area = $input->getOption('area'); $format = $input->getOption('format'); diff --git a/DependencyInjection/Compiler/ConfigurationPass.php b/DependencyInjection/Compiler/ConfigurationPass.php index c2400fb44..df91bddc1 100644 --- a/DependencyInjection/Compiler/ConfigurationPass.php +++ b/DependencyInjection/Compiler/ConfigurationPass.php @@ -14,6 +14,7 @@ use Nelmio\ApiDocBundle\ModelDescriber\FormModelDescriber; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; /** @@ -29,7 +30,7 @@ public function process(ContainerBuilder $container): void $container->register('nelmio_api_doc.model_describers.form', FormModelDescriber::class) ->setPublic(false) ->addArgument(new Reference('form.factory')) - ->addArgument(new Reference('annotations.reader')) + ->addArgument(new Reference('annotations.reader', ContainerInterface::NULL_ON_INVALID_REFERENCE)) ->addArgument($container->getParameter('nelmio_api_doc.media_types')) ->addArgument($container->getParameter('nelmio_api_doc.use_validation_groups')) ->addTag('nelmio_api_doc.model_describer', ['priority' => 100]); diff --git a/DependencyInjection/NelmioApiDocExtension.php b/DependencyInjection/NelmioApiDocExtension.php index cf6ac501e..edcca5cb7 100644 --- a/DependencyInjection/NelmioApiDocExtension.php +++ b/DependencyInjection/NelmioApiDocExtension.php @@ -25,6 +25,7 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; @@ -94,7 +95,7 @@ public function load(array $configs, ContainerBuilder $container): void ->setArguments([ new Reference(sprintf('nelmio_api_doc.routes.%s', $area)), new Reference('nelmio_api_doc.controller_reflector'), - new Reference('annotations.reader'), // We cannot use the cached version of the annotation reader since the construction of the annotations is context dependant... + new Reference('annotations.reader', ContainerInterface::NULL_ON_INVALID_REFERENCE), // We cannot use the cached version of the annotation reader since the construction of the annotations is context dependant... new Reference('logger'), ]) ->addTag(sprintf('nelmio_api_doc.describer.%s', $area), ['priority' => -200]); @@ -123,7 +124,7 @@ public function load(array $configs, ContainerBuilder $container): void (new Definition(FilteredRouteCollectionBuilder::class)) ->setArguments( [ - new Reference('annotation_reader'), // Here we use the cached version as we don't deal with @OA annotations in this service + new Reference('annotation_reader', ContainerInterface::NULL_ON_INVALID_REFERENCE), // Here we use the cached version as we don't deal with @OA annotations in this service new Reference('nelmio_api_doc.controller_reflector'), $area, $areaConfig, @@ -181,7 +182,7 @@ public function load(array $configs, ContainerBuilder $container): void ->setPublic(false) ->setArguments([ new Reference('jms_serializer.metadata_factory'), - new Reference('annotations.reader'), + new Reference('annotations.reader', ContainerInterface::NULL_ON_INVALID_REFERENCE), $config['media_types'], $jmsNamingStrategy, $container->getParameter('nelmio_api_doc.use_validation_groups'), diff --git a/Describer/OpenApiPhpDescriber.php b/Describer/OpenApiPhpDescriber.php index f40e59c95..62156a611 100644 --- a/Describer/OpenApiPhpDescriber.php +++ b/Describer/OpenApiPhpDescriber.php @@ -33,11 +33,15 @@ final class OpenApiPhpDescriber private $routeCollection; private $controllerReflector; + + /** + * @var Reader|null + */ private $annotationReader; private $logger; private $overwrite; - public function __construct(RouteCollection $routeCollection, ControllerReflector $controllerReflector, Reader $annotationReader, LoggerInterface $logger, bool $overwrite = false) + public function __construct(RouteCollection $routeCollection, ControllerReflector $controllerReflector, ?Reader $annotationReader, LoggerInterface $logger, bool $overwrite = false) { $this->routeCollection = $routeCollection; $this->controllerReflector = $controllerReflector; @@ -51,7 +55,7 @@ public function describe(OA\OpenApi $api) $classAnnotations = []; /** @var \ReflectionMethod $method */ - foreach ($this->getMethodsToParse() as $method => list($path, $httpMethods, $routeName)) { + foreach ($this->getMethodsToParse() as $method => [$path, $httpMethods, $routeName]) { $declaringClass = $method->getDeclaringClass(); $path = Util::getPath($api, $path); @@ -65,16 +69,25 @@ public function describe(OA\OpenApi $api) $this->setContext($context); if (!array_key_exists($declaringClass->getName(), $classAnnotations)) { - $classAnnotations = array_filter($this->annotationReader->getClassAnnotations($declaringClass), function ($v) { + if (null !== $this->annotationReader) { + $classAnnotations = $this->annotationReader->getClassAnnotations($declaringClass); + } + + $classAnnotations = array_filter($classAnnotations, function ($v) { return $v instanceof OA\AbstractAnnotation; }); + $classAnnotations = array_merge($classAnnotations, $this->getAttributesAsAnnotation($declaringClass, $context)); $classAnnotations[$declaringClass->getName()] = $classAnnotations; } - $annotations = array_filter($this->annotationReader->getMethodAnnotations($method), function ($v) { - return $v instanceof OA\AbstractAnnotation; - }); + $annotations = []; + if (null !== $this->annotationReader) { + $annotations = array_filter($this->annotationReader->getMethodAnnotations($method), function ($v) { + return $v instanceof OA\AbstractAnnotation; + }); + } + $annotations = array_merge($annotations, $this->getAttributesAsAnnotation($method, $context)); if (0 === count($annotations) && 0 === count($classAnnotations[$declaringClass->getName()])) { diff --git a/ModelDescriber/Annotations/AnnotationsReader.php b/ModelDescriber/Annotations/AnnotationsReader.php index 85f496dcf..b483793ce 100644 --- a/ModelDescriber/Annotations/AnnotationsReader.php +++ b/ModelDescriber/Annotations/AnnotationsReader.php @@ -21,22 +21,16 @@ */ class AnnotationsReader { - private $annotationsReader; - private $modelRegistry; - private $phpDocReader; private $openApiAnnotationsReader; private $symfonyConstraintAnnotationReader; public function __construct( - Reader $annotationsReader, + ?Reader $annotationsReader, ModelRegistry $modelRegistry, array $mediaTypes, bool $useValidationGroups = false ) { - $this->annotationsReader = $annotationsReader; - $this->modelRegistry = $modelRegistry; - $this->phpDocReader = new PropertyPhpDocReader(); $this->openApiAnnotationsReader = new OpenApiAnnotationsReader($annotationsReader, $modelRegistry, $mediaTypes); $this->symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader( diff --git a/ModelDescriber/Annotations/OpenApiAnnotationsReader.php b/ModelDescriber/Annotations/OpenApiAnnotationsReader.php index e0f1753ea..026178d2a 100644 --- a/ModelDescriber/Annotations/OpenApiAnnotationsReader.php +++ b/ModelDescriber/Annotations/OpenApiAnnotationsReader.php @@ -28,10 +28,13 @@ class OpenApiAnnotationsReader { use SetsContextTrait; + /** + * @var Reader|null + */ private $annotationsReader; private $modelRegister; - public function __construct(Reader $annotationsReader, ModelRegistry $modelRegistry, array $mediaTypes) + public function __construct(?Reader $annotationsReader, ModelRegistry $modelRegistry, array $mediaTypes) { $this->annotationsReader = $annotationsReader; $this->modelRegister = new ModelRegister($modelRegistry, $mediaTypes); @@ -97,12 +100,14 @@ private function getAnnotation(Context $parentContext, $reflection, string $clas } } - if ($reflection instanceof \ReflectionClass) { - return $this->annotationsReader->getClassAnnotation($reflection, $className); - } elseif ($reflection instanceof \ReflectionProperty) { - return $this->annotationsReader->getPropertyAnnotation($reflection, $className); - } elseif ($reflection instanceof \ReflectionMethod) { - return $this->annotationsReader->getMethodAnnotation($reflection, $className); + if (null !== $this->annotationsReader) { + if ($reflection instanceof \ReflectionClass) { + return $this->annotationsReader->getClassAnnotation($reflection, $className); + } elseif ($reflection instanceof \ReflectionProperty) { + return $this->annotationsReader->getPropertyAnnotation($reflection, $className); + } elseif ($reflection instanceof \ReflectionMethod) { + return $this->annotationsReader->getMethodAnnotation($reflection, $className); + } } } finally { $this->setContext(null); diff --git a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php index aa5701849..ee3b9bb6d 100644 --- a/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php +++ b/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php @@ -28,7 +28,7 @@ class SymfonyConstraintAnnotationReader use SetsContextTrait; /** - * @var Reader + * @var Reader|null */ private $annotationsReader; @@ -42,7 +42,7 @@ class SymfonyConstraintAnnotationReader */ private $useValidationGroups; - public function __construct(Reader $annotationsReader, bool $useValidationGroups=false) + public function __construct(?Reader $annotationsReader, bool $useValidationGroups=false) { $this->annotationsReader = $annotationsReader; $this->useValidationGroups = $useValidationGroups; @@ -215,10 +215,12 @@ private function locateAnnotations($reflection): \Traversable } } - if ($reflection instanceof \ReflectionProperty) { - yield from $this->annotationsReader->getPropertyAnnotations($reflection); - } elseif ($reflection instanceof \ReflectionMethod) { - yield from $this->annotationsReader->getMethodAnnotations($reflection); + if (null !== $this->annotationsReader) { + if ($reflection instanceof \ReflectionProperty) { + yield from $this->annotationsReader->getPropertyAnnotations($reflection); + } elseif ($reflection instanceof \ReflectionMethod) { + yield from $this->annotationsReader->getMethodAnnotations($reflection); + } } } diff --git a/ModelDescriber/FormModelDescriber.php b/ModelDescriber/FormModelDescriber.php index 933d411f4..4a5fd70a2 100644 --- a/ModelDescriber/FormModelDescriber.php +++ b/ModelDescriber/FormModelDescriber.php @@ -40,6 +40,10 @@ final class FormModelDescriber implements ModelDescriberInterface, ModelRegistry use SetsContextTrait; private $formFactory; + + /** + * @var Reader|null + */ private $doctrineReader; private $mediaTypes; private $useValidationGroups; @@ -52,9 +56,6 @@ public function __construct( ) { $this->formFactory = $formFactory; $this->doctrineReader = $reader; - if (null === $reader) { - @trigger_error(sprintf('Not passing a doctrine reader to the constructor of %s is deprecated since version 3.8 and won\'t be allowed in version 5.', self::class), E_USER_DEPRECATED); - } if (null === $mediaTypes) { $mediaTypes = ['json']; diff --git a/ModelDescriber/JMSModelDescriber.php b/ModelDescriber/JMSModelDescriber.php index 991228fd2..6ab63be04 100644 --- a/ModelDescriber/JMSModelDescriber.php +++ b/ModelDescriber/JMSModelDescriber.php @@ -40,6 +40,9 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn private $namingStrategy; + /** + * @var Reader|null + */ private $doctrineReader; private $contexts = []; @@ -60,7 +63,7 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn public function __construct( MetadataFactoryInterface $factory, - Reader $reader, + ?Reader $reader, array $mediaTypes, ?PropertyNamingStrategyInterface $namingStrategy = null, bool $useValidationGroups = false, diff --git a/ModelDescriber/ObjectModelDescriber.php b/ModelDescriber/ObjectModelDescriber.php index 6f81f7b97..6ae19d345 100644 --- a/ModelDescriber/ObjectModelDescriber.php +++ b/ModelDescriber/ObjectModelDescriber.php @@ -35,7 +35,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar private $propertyInfo; /** @var ClassMetadataFactoryInterface|null */ private $classMetadataFactory; - /** @var Reader */ + /** @var Reader|null */ private $doctrineReader; /** @var PropertyDescriberInterface[] */ private $propertyDescribers; @@ -48,7 +48,7 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar public function __construct( PropertyInfoExtractorInterface $propertyInfo, - Reader $reader, + ?Reader $reader, iterable $propertyDescribers, array $mediaTypes, NameConverterInterface $nameConverter = null, diff --git a/Resources/config/fos_rest.xml b/Resources/config/fos_rest.xml index 32c3045a2..74c99ba82 100644 --- a/Resources/config/fos_rest.xml +++ b/Resources/config/fos_rest.xml @@ -5,7 +5,7 @@ - + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 0d9801312..9ccd5bad4 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -75,7 +75,7 @@ - + diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index e4c4e1a93..e7bbeeaa9 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -27,13 +27,13 @@ final class FosRestDescriber implements RouteDescriberInterface { use RouteDescriberTrait; - /** @var Reader */ + /** @var Reader|null */ private $annotationReader; /** @var string[] */ private $mediaTypes; - public function __construct(Reader $annotationReader, array $mediaTypes) + public function __construct(?Reader $annotationReader, array $mediaTypes) { $this->annotationReader = $annotationReader; $this->mediaTypes = $mediaTypes; @@ -41,7 +41,9 @@ public function __construct(Reader $annotationReader, array $mediaTypes) public function describe(OA\OpenApi $api, Route $route, \ReflectionMethod $reflectionMethod) { - $annotations = $this->annotationReader->getMethodAnnotations($reflectionMethod); + $annotations = null !== $this->annotationReader + ? $this->annotationReader->getMethodAnnotations($reflectionMethod) + : []; $annotations = array_filter($annotations, static function ($value) { return $value instanceof RequestParam || $value instanceof QueryParam; }); diff --git a/Routing/FilteredRouteCollectionBuilder.php b/Routing/FilteredRouteCollectionBuilder.php index 518603f69..f1fcf5313 100644 --- a/Routing/FilteredRouteCollectionBuilder.php +++ b/Routing/FilteredRouteCollectionBuilder.php @@ -21,7 +21,7 @@ final class FilteredRouteCollectionBuilder { - /** @var Reader */ + /** @var Reader|null */ private $annotationReader; /** @var ControllerReflector */ @@ -34,7 +34,7 @@ final class FilteredRouteCollectionBuilder private $options; public function __construct( - Reader $annotationReader, + ?Reader $annotationReader, ControllerReflector $controllerReflector, string $area, array $options = [] @@ -137,7 +137,7 @@ private function matchAnnotation(Route $route): bool /** @var Areas|null $areas */ $areas = $this->getAttributesAsAnnotation($reflectionMethod->getDeclaringClass(), Areas::class)[0] ?? null; - if (null === $areas) { + if (null === $areas && null !== $this->annotationReader) { /** @var Areas|null $areas */ $areas = $this->annotationReader->getMethodAnnotation( $reflectionMethod, @@ -167,7 +167,10 @@ private function defaultRouteDisabled(Route $route): bool return false; } - $annotations = $this->annotationReader->getMethodAnnotations($method); + $annotations = null !== $this->annotationReader + ? $this->annotationReader->getMethodAnnotations($method) + : []; + if (method_exists(\ReflectionMethod::class, 'getAttributes')) { $annotations = array_merge($annotations, array_map(function (\ReflectionAttribute $attribute) { return $attribute->newInstance(); diff --git a/Tests/Functional/BazingaFunctionalTest.php b/Tests/Functional/BazingaFunctionalTest.php index d7f914609..e10514f34 100644 --- a/Tests/Functional/BazingaFunctionalTest.php +++ b/Tests/Functional/BazingaFunctionalTest.php @@ -12,12 +12,17 @@ namespace Nelmio\ApiDocBundle\Tests\Functional; use Hateoas\Configuration\Embedded; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; class BazingaFunctionalTest extends WebTestCase { protected function setUp(): void { + if (Kernel::MAJOR_VERSION < 7) { + $this->markTestSkipped('Not supported in symfony 7'); + } + parent::setUp(); static::createClient([], ['HTTP_HOST' => 'api.example.com']); diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index 8985a5098..0dbf4efb3 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -11,12 +11,11 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -if (\PHP_VERSION_ID >= 80100) { - /** - * @Route("/api", name="api_", host="api.example.com") - */ +if (Kernel::MAJOR_VERSION >= 7) { + #[Route("/api", name: 'api_', host: 'api.example.com')] class ApiController extends ApiController81 { } diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index b12f5cd06..69d8ed490 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -32,7 +32,7 @@ class ApiController81 extends ApiController80 ])] #[OA\Parameter(ref: '#/components/parameters/test')] #[Route('/article_attributes/{id}', methods: ['GET'])] - #[OA\Parameter(name: 'Accept-Version', in: 'header', attachables: [new OA\Schema(type: 'string')])] + #[OA\Parameter(name: 'Accept-Version', in: 'header', schema: new OA\Schema(type: 'string'))] public function fetchArticleActionWithAttributes() { } diff --git a/Tests/Functional/Controller/ClassApiController.php b/Tests/Functional/Controller/ClassApiController.php index 21bbd0e45..a3a4b6d19 100644 --- a/Tests/Functional/Controller/ClassApiController.php +++ b/Tests/Functional/Controller/ClassApiController.php @@ -13,19 +13,34 @@ use Nelmio\ApiDocBundle\Annotation\Security; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Response; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -/** - * @Route("/api", host="api.example.com") - * @Security(name="basic") - */ -class ClassApiController -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @Route("/security/class") - * @OA\Response(response="201", description="") + * @Route("/api", host="api.example.com") + * @Security(name="basic") */ - public function securityAction() + class ClassApiController + { + /** + * @Route("/security/class") + * @OA\Response(response="201", description="") + */ + public function securityAction() + { + } + } +} else { + #[Security(name: 'basic')] + #[Route("/api", host: "api.example.com")] + class ClassApiController { + #[Response(response: 201, description: '')] + #[Route("/security/class")] + public function securityAction() + { + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/Controller/InvokableController.php b/Tests/Functional/Controller/InvokableController.php index b640b70be..86e4a9dbb 100644 --- a/Tests/Functional/Controller/InvokableController.php +++ b/Tests/Functional/Controller/InvokableController.php @@ -12,20 +12,36 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Response; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -/** - * Prevents a regression (see https://github.com/nelmio/NelmioApiDocBundle/issues/1559). - * - * @Route("/api/invoke", host="api.example.com", name="invokable", methods={"GET"}) - * @OA\Response( - * response=200, - * description="Invokable!" - * ) - */ -class InvokableController -{ - public function __invoke() +if (Kernel::MAJOR_VERSION < 7) { + /** + * Prevents a regression (see https://github.com/nelmio/NelmioApiDocBundle/issues/1559). + * + * @Route("/api/invoke", host="api.example.com", name="invokable", methods={"GET"}) + * @OA\Response( + * response=200, + * description="Invokable!" + * ) + */ + class InvokableController + { + public function __invoke() + { + } + } +} else { + /** + * Prevents a regression (see https://github.com/nelmio/NelmioApiDocBundle/issues/1559). + */ + #[Response(response: 200, description: 'Invokable!')] + #[Route("/api/invoke", host: "api.example.com", name: "invokable", methods: ["GET"])] + class InvokableController { + public function __invoke() + { + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/Controller/SerializedNameController.php b/Tests/Functional/Controller/SerializedNameController.php index 736a2669f..dd9f3fa7b 100644 --- a/Tests/Functional/Controller/SerializedNameController.php +++ b/Tests/Functional/Controller/SerializedNameController.php @@ -13,25 +13,43 @@ use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\SerializedNameEnt; +use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\Symfony7\SerializedNameEntity; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Response; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -/** - * This controller is only loaded when SerializedName exists (sf >= 4.2). - * - * @Route("/api", host="api.example.com") - */ -class SerializedNameController -{ +if (Kernel::MAJOR_VERSION < 7) { + /** + * This controller is only loaded when SerializedName exists (sf >= 4.2). + * + * @Route("/api", host="api.example.com") + */ + class SerializedNameController + { + /** + * @OA\Response( + * response="200", + * description="success", + * @Model(type=SerializedNameEnt::class) + * ) + * @Route("/serializename", methods={"GET"}) + */ + public function serializedNameAction() + { + } + } +} else { /** - * @OA\Response( - * response="200", - * description="success", - * @Model(type=SerializedNameEnt::class) - * ) - * @Route("/serializename", methods={"GET"}) + * This controller is only loaded when SerializedName exists (sf >= 4.2). */ - public function serializedNameAction() + #[Route("/api", host: "api.example.com")] + class SerializedNameController { + #[Response(response: 200, description: 'success', attachables: [new Model(type: SerializedNameEntity::class)])] + #[Route("/serializename", methods: ["GET"])] + public function serializedNameAction() + { + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/Controller/TestController.php b/Tests/Functional/Controller/TestController.php index 7e887e613..71bd8b1e4 100644 --- a/Tests/Functional/Controller/TestController.php +++ b/Tests/Functional/Controller/TestController.php @@ -12,21 +12,35 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Response; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -/** - * @Route("/test", host="api-test.example.com") - */ -class TestController -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @OA\Response( - * response="200", - * description="Test" - * ) - * @Route("/test/", methods={"GET"}) + * @Route("/test", host="api-test.example.com") */ - public function testAction() + class TestController + { + /** + * @OA\Response( + * response="200", + * description="Test" + * ) + * @Route("/test/", methods={"GET"}) + */ + public function testAction() + { + } + } +} else { + #[Route('/test', host: 'api-test.example.com')] + class TestController { + #[Response(response: 200, description: 'Test')] + #[Route("/test/", methods: ["GET"])] + public function testAction() + { + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/Controller/UndocumentedController.php b/Tests/Functional/Controller/UndocumentedController.php index 98fbe6562..92904cb1e 100644 --- a/Tests/Functional/Controller/UndocumentedController.php +++ b/Tests/Functional/Controller/UndocumentedController.php @@ -11,19 +11,36 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -/** - * @Route(host="api.example.com") - */ -class UndocumentedController -{ + +if (Kernel::MAJOR_VERSION < 7) { /** - * This path is excluded by the config (only /api allowed). - * - * @Route("/undocumented", methods={"GET"}) + * @Route(host="api.example.com") */ - public function undocumentedAction() + class UndocumentedController + { + /** + * This path is excluded by the config (only /api allowed). + * + * @Route("/undocumented", methods={"GET"}) + */ + public function undocumentedAction() + { + } + } +} else { + #[Route(host: "api.example.com")] + class UndocumentedController { + /** + * This path is excluded by the config (only /api allowed). + * + */ + #[Route("/undocumented", methods: ["GET"])] + public function undocumentedAction() + { + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/Entity/Article.php b/Tests/Functional/Entity/Article.php index 922e54620..a67505b01 100644 --- a/Tests/Functional/Entity/Article.php +++ b/Tests/Functional/Entity/Article.php @@ -11,21 +11,37 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Doctrine\Common\Annotations\AnnotationReader; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\Groups; -/** - * @author Guilhem N. - */ -class Article -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @Groups({"light"}) + * @author Guilhem N. */ - public function setAuthor(User $author) + class Article { - } + /** + * @Groups({"light"}) + */ + public function setAuthor(User $author) + { + } - public function setContent(string $content) + public function setContent(string $content) + { + } + } +} else { + class Article { + #[Groups(["light"])] + public function setAuthor(User $author) + { + } + + public function setContent(string $content) + { + } } } diff --git a/Tests/Functional/Entity/EntityWithAlternateType.php b/Tests/Functional/Entity/EntityWithAlternateType.php index 1b9538c05..9f5c03afd 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType.php +++ b/Tests/Functional/Entity/EntityWithAlternateType.php @@ -14,22 +14,44 @@ use ArrayIterator; use IteratorAggregate; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Items; +use OpenApi\Attributes\Schema; +use Symfony\Component\HttpKernel\Kernel; -/** - * @OA\Schema(type="array", @OA\Items(type="string")) - */ -class EntityWithAlternateType implements IteratorAggregate -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @var string + * @OA\Schema(type="array", @OA\Items(type="string")) */ - public $ignored = 'this property should be ignored because of the annotation above'; + class EntityWithAlternateType implements IteratorAggregate + { + /** + * @var string + */ + public $ignored = 'this property should be ignored because of the annotation above'; - public function getIterator(): ArrayIterator + public function getIterator(): ArrayIterator + { + return new ArrayIterator([ + 'abc', + 'def', + ]); + } + } +} else { + #[Schema(type: 'array', items: new Items(type: 'string'))] + class EntityWithAlternateType implements IteratorAggregate { - return new ArrayIterator([ - 'abc', - 'def', - ]); + /** + * @var string + */ + public $ignored = 'this property should be ignored because of the annotation above'; + + public function getIterator(): ArrayIterator + { + return new ArrayIterator([ + 'abc', + 'def', + ]); + } } } diff --git a/Tests/Functional/Entity/EntityWithNullableSchemaSet.php b/Tests/Functional/Entity/EntityWithNullableSchemaSet.php index 615a41f0e..216800936 100644 --- a/Tests/Functional/Entity/EntityWithNullableSchemaSet.php +++ b/Tests/Functional/Entity/EntityWithNullableSchemaSet.php @@ -12,48 +12,91 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Property; +use Symfony\Component\HttpKernel\Kernel; -class EntityWithNullableSchemaSet -{ - /** - * @var ?string - * - * @OA\Property() - */ - public $nullablePropertyNullableNotSet; - - /** - * @var ?string - * - * @OA\Property(nullable=false) - */ - public $nullablePropertyNullableFalseSet; - - /** - * @var ?string - * - * @OA\Property(nullable=true) - */ - public $nullablePropertyNullableTrueSet; - - /** - * @var string - * - * @OA\Property() - */ - public $nonNullablePropertyNullableNotSet; - - /** - * @var string - * - * @OA\Property(nullable=false) - */ - public $nonNullablePropertyNullableFalseSet; - - /** - * @var string - * - * @OA\Property(nullable=true) - */ - public $nonNullablePropertyNullableTrueSet; +if (Kernel::MAJOR_VERSION < 7) { + class EntityWithNullableSchemaSet + { + /** + * @var ?string + * + * @OA\Property() + */ + public $nullablePropertyNullableNotSet; + + /** + * @var ?string + * + * @OA\Property(nullable=false) + */ + public $nullablePropertyNullableFalseSet; + + /** + * @var ?string + * + * @OA\Property(nullable=true) + */ + public $nullablePropertyNullableTrueSet; + + /** + * @var string + * + * @OA\Property() + */ + public $nonNullablePropertyNullableNotSet; + + /** + * @var string + * + * @OA\Property(nullable=false) + */ + public $nonNullablePropertyNullableFalseSet; + + /** + * @var string + * + * @OA\Property(nullable=true) + */ + public $nonNullablePropertyNullableTrueSet; + } +} else { + class EntityWithNullableSchemaSet + { + /** + * @var ?string + */ + #[Property] + public $nullablePropertyNullableNotSet; + + /** + * @var ?string + */ + #[Property(nullable: false)] + public $nullablePropertyNullableFalseSet; + + /** + * @var ?string + */ + #[Property(nullable: true)] + public $nullablePropertyNullableTrueSet; + + /** + * @var string + */ + #[Property] + public $nonNullablePropertyNullableNotSet; + + /** + * @var string + */ + #[Property(nullable: false)] + public $nonNullablePropertyNullableFalseSet; + + /** + * @var string + */ + #[Property(nullable: true)] + public $nonNullablePropertyNullableTrueSet; + } } diff --git a/Tests/Functional/Entity/EntityWithObjectType.php b/Tests/Functional/Entity/EntityWithObjectType.php index ba0415c23..1d17f8cdb 100644 --- a/Tests/Functional/Entity/EntityWithObjectType.php +++ b/Tests/Functional/Entity/EntityWithObjectType.php @@ -12,14 +12,28 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Schema; +use Symfony\Component\HttpKernel\Kernel; -/** - * @OA\Schema(type="object") - */ -class EntityWithObjectType -{ + +if (Kernel::MAJOR_VERSION < 7) { /** - * @var string + * @OA\Schema(type="object") */ - public $notIgnored = 'this should be read'; + class EntityWithObjectType + { + /** + * @var string + */ + public $notIgnored = 'this should be read'; + } +} else { + #[Schema(type: 'object')] + class EntityWithObjectType + { + /** + * @var string + */ + public $notIgnored = 'this should be read'; + } } diff --git a/Tests/Functional/Entity/EntityWithRef.php b/Tests/Functional/Entity/EntityWithRef.php index f149bfb29..ca48276c2 100644 --- a/Tests/Functional/Entity/EntityWithRef.php +++ b/Tests/Functional/Entity/EntityWithRef.php @@ -12,14 +12,27 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Schema; +use Symfony\Component\HttpKernel\Kernel; -/** - * @OA\Schema(ref="#/components/schemas/Test") - */ -class EntityWithRef -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @var string + * @OA\Schema(ref="#/components/schemas/Test") */ - public $ignored = 'this property should be ignored because of the annotation above'; + class EntityWithRef + { + /** + * @var string + */ + public $ignored = 'this property should be ignored because of the annotation above'; + } +} else { + #[Schema(ref: '#/components/schemas/Test')] + class EntityWithRef + { + /** + * @var string + */ + public $ignored = 'this property should be ignored because of the annotation above'; + } } diff --git a/Tests/Functional/Entity/SymfonyConstraints.php b/Tests/Functional/Entity/SymfonyConstraints.php index 86e3d1600..b802b460b 100644 --- a/Tests/Functional/Entity/SymfonyConstraints.php +++ b/Tests/Functional/Entity/SymfonyConstraints.php @@ -12,189 +12,365 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Validator\Constraints as Assert; -class SymfonyConstraints -{ - /** - * @var int - * - * @Assert\NotBlank(groups={"test"}) - */ - private $propertyNotBlank; - - /** - * @var int - * - * @Assert\NotNull() - */ - private $propertyNotNull; - - /** - * @var int - * - * @Assert\Length(min="0", max="50") - */ - private $propertyAssertLength; - - /** - * @var int - * - * @Assert\Regex(pattern="/[a-z]{2}/") - */ - private $propertyRegex; - - /** - * @var int - * - * @Assert\Count(min="0", max="10") - */ - private $propertyCount; - - /** - * @var int - * - * @Assert\Choice(choices={"choice1", "choice2"}) - */ - private $propertyChoice; - - /** - * @var int - * - * @Assert\Choice(callback={SymfonyConstraints::class,"fetchAllowedChoices"}) - */ - private $propertyChoiceWithCallback; - - /** - * @var int - * - * @Assert\Choice(callback="fetchAllowedChoices") - */ - private $propertyChoiceWithCallbackWithoutClass; - - /** - * @var string[] - * - * @Assert\Choice(multiple=true, choices={"choice1", "choice2"}) - */ - private $propertyChoiceWithMultiple; - - /** - * @var int - * - * @Assert\Expression( - * "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", - * message="If this is a tech post, the category should be either php or symfony!" - * ) - */ - private $propertyExpression; - - /** - * @var int - * - * @Assert\Range(min=1, max=5) - */ - private $propertyRange; - - /** - * @var int - * - * @Assert\LessThan(42) - */ - private $propertyLessThan; - - /** - * @var int - * - * @Assert\LessThanOrEqual(23) - */ - private $propertyLessThanOrEqual; - - /** - * @var int - * - * @CustomAssert\CompoundValidationRule() - */ - private $propertyWithCompoundValidationRule; - - public function setPropertyWithCompoundValidationRule(int $propertyWithCompoundValidationRule): void +if (Kernel::MAJOR_VERSION < 7) { + class SymfonyConstraints { - $this->propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; + /** + * @var int + * + * @Assert\NotBlank(groups={"test"}) + */ + private $propertyNotBlank; + + /** + * @var int + * + * @Assert\NotNull() + */ + private $propertyNotNull; + + /** + * @var int + * + * @Assert\Length(min="0", max="50") + */ + private $propertyAssertLength; + + /** + * @var int + * + * @Assert\Regex(pattern="/[a-z]{2}/") + */ + private $propertyRegex; + + /** + * @var int + * + * @Assert\Count(min="0", max="10") + */ + private $propertyCount; + + /** + * @var int + * + * @Assert\Choice(choices={"choice1", "choice2"}) + */ + private $propertyChoice; + + /** + * @var int + * + * @Assert\Choice(callback={SymfonyConstraints::class,"fetchAllowedChoices"}) + */ + private $propertyChoiceWithCallback; + + /** + * @var int + * + * @Assert\Choice(callback="fetchAllowedChoices") + */ + private $propertyChoiceWithCallbackWithoutClass; + + /** + * @var string[] + * + * @Assert\Choice(multiple=true, choices={"choice1", "choice2"}) + */ + private $propertyChoiceWithMultiple; + + /** + * @var int + * + * @Assert\Expression( + * "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", + * message="If this is a tech post, the category should be either php or symfony!" + * ) + */ + private $propertyExpression; + + /** + * @var int + * + * @Assert\Range(min=1, max=5) + */ + private $propertyRange; + + /** + * @var int + * + * @Assert\LessThan(42) + */ + private $propertyLessThan; + + /** + * @var int + * + * @Assert\LessThanOrEqual(23) + */ + private $propertyLessThanOrEqual; + + /** + * @var int + * + * @CustomAssert\CompoundValidationRule() + */ + private $propertyWithCompoundValidationRule; + + public function setPropertyWithCompoundValidationRule(int $propertyWithCompoundValidationRule): void + { + $this->propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; + } + + /** + * @Assert\Count(min="0", max="10") + */ + public function setPropertyNotBlank(int $propertyNotBlank): void + { + $this->propertyNotBlank = $propertyNotBlank; + } + + public function setPropertyNotNull(int $propertyNotNull): void + { + $this->propertyNotNull = $propertyNotNull; + } + + public function setPropertyAssertLength(int $propertyAssertLength): void + { + $this->propertyAssertLength = $propertyAssertLength; + } + + public function setPropertyRegex(int $propertyRegex): void + { + $this->propertyRegex = $propertyRegex; + } + + public function setPropertyCount(int $propertyCount): void + { + $this->propertyCount = $propertyCount; + } + + public function setPropertyChoice(int $propertyChoice): void + { + $this->propertyChoice = $propertyChoice; + } + + public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void + { + $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; + } + + public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void + { + $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; + } + + public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void + { + $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; + } + + public function setPropertyExpression(int $propertyExpression): void + { + $this->propertyExpression = $propertyExpression; + } + + public function setPropertyRange(int $propertyRange): void + { + $this->propertyRange = $propertyRange; + } + + public function setPropertyLessThan(int $propertyLessThan): void + { + $this->propertyLessThan = $propertyLessThan; + } + + public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void + { + $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; + } + + /** + * @return array + */ + public static function fetchAllowedChoices() + { + return ['choice1', 'choice2']; + } } - - /** - * @Assert\Count(min="0", max="10") - */ - public function setPropertyNotBlank(int $propertyNotBlank): void - { - $this->propertyNotBlank = $propertyNotBlank; - } - - public function setPropertyNotNull(int $propertyNotNull): void - { - $this->propertyNotNull = $propertyNotNull; - } - - public function setPropertyAssertLength(int $propertyAssertLength): void - { - $this->propertyAssertLength = $propertyAssertLength; - } - - public function setPropertyRegex(int $propertyRegex): void - { - $this->propertyRegex = $propertyRegex; - } - - public function setPropertyCount(int $propertyCount): void - { - $this->propertyCount = $propertyCount; - } - - public function setPropertyChoice(int $propertyChoice): void - { - $this->propertyChoice = $propertyChoice; - } - - public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void - { - $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; - } - - public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void - { - $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; - } - - public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void - { - $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; - } - - public function setPropertyExpression(int $propertyExpression): void - { - $this->propertyExpression = $propertyExpression; - } - - public function setPropertyRange(int $propertyRange): void - { - $this->propertyRange = $propertyRange; - } - - public function setPropertyLessThan(int $propertyLessThan): void - { - $this->propertyLessThan = $propertyLessThan; - } - - public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void - { - $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; - } - - /** - * @return array - */ - public static function fetchAllowedChoices() +} else { + class SymfonyConstraints { - return ['choice1', 'choice2']; + /** + * @var int + */ + #[Assert\NotBlank(groups: ["test"])] + private $propertyNotBlank; + + /** + * @var int + * + */ + #[Assert\NotNull()] + private $propertyNotNull; + + /** + * @var int + * + */ + #[Assert\Length(min: "0", max: "50")] + private $propertyAssertLength; + + /** + * @var int + * + */ + #[Assert\Regex(pattern: "/[a-z]{2}/")] + private $propertyRegex; + + /** + * @var int + * + */ + #[Assert\Count(min: "0", max: "10")] + private $propertyCount; + + /** + * @var int + */ + #[Assert\Choice(choices: ["choice1", "choice2"])] + private $propertyChoice; + + /** + * @var int + */ + #[Assert\Choice(callback: [self::class, "fetchAllowedChoices"])] + private $propertyChoiceWithCallback; + + /** + * @var int + */ + #[Assert\Choice(callback: "fetchAllowedChoices")] + private $propertyChoiceWithCallbackWithoutClass; + + /** + * @var string[] + */ + #[Assert\Choice(multiple: true, choices: ["choice1", "choice2"])] + private $propertyChoiceWithMultiple; + + /** + * @var int + */ + #[Assert\Expression( + "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", + message: "If this is a tech post, the category should be either php or symfony!" + )] + private $propertyExpression; + + /** + * @var int + */ + #[Assert\Range(min: 1, max: 5)] + private $propertyRange; + + /** + * @var int + */ + #[Assert\LessThan(42)] + private $propertyLessThan; + + /** + * @var int + */ + #[Assert\LessThanOrEqual(23)] + private $propertyLessThanOrEqual; + + /** + * @var int + */ + #[CustomAssert\CompoundValidationRule] + private $propertyWithCompoundValidationRule; + + public function setPropertyWithCompoundValidationRule(int $propertyWithCompoundValidationRule): void + { + $this->propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; + } + + #[Assert\Count(min: "0", max: "10")] + public function setPropertyNotBlank(int $propertyNotBlank): void + { + $this->propertyNotBlank = $propertyNotBlank; + } + + public function setPropertyNotNull(int $propertyNotNull): void + { + $this->propertyNotNull = $propertyNotNull; + } + + public function setPropertyAssertLength(int $propertyAssertLength): void + { + $this->propertyAssertLength = $propertyAssertLength; + } + + public function setPropertyRegex(int $propertyRegex): void + { + $this->propertyRegex = $propertyRegex; + } + + public function setPropertyCount(int $propertyCount): void + { + $this->propertyCount = $propertyCount; + } + + public function setPropertyChoice(int $propertyChoice): void + { + $this->propertyChoice = $propertyChoice; + } + + public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void + { + $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; + } + + public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void + { + $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; + } + + public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void + { + $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; + } + + public function setPropertyExpression(int $propertyExpression): void + { + $this->propertyExpression = $propertyExpression; + } + + public function setPropertyRange(int $propertyRange): void + { + $this->propertyRange = $propertyRange; + } + + public function setPropertyLessThan(int $propertyLessThan): void + { + $this->propertyLessThan = $propertyLessThan; + } + + public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void + { + $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; + } + + /** + * @return array + */ + public static function fetchAllowedChoices() + { + return ['choice1', 'choice2']; + } } } diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php index 8a986dd75..cf83b6cb3 100644 --- a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php @@ -12,32 +12,61 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Items; +use OpenApi\Attributes\Property; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -class SymfonyConstraintsWithValidationGroups -{ - /** - * @var int - * - * @Groups("test") - * @Assert\NotBlank(groups={"test"}) - * @Assert\Range(min=1, max=100) - */ - public $property; - - /** - * @var int - * - * @Assert\Range(min=1, max=100) - */ - public $propertyInDefaultGroup; - - /** - * @var array - * - * @OA\Property(type="array", @OA\Items(type="string")) - * @Assert\Valid - */ - public $propertyArray; +if (Kernel::MAJOR_VERSION < 7) { + class SymfonyConstraintsWithValidationGroups + { + /** + * @var int + * + * @Groups("test") + * @Assert\NotBlank(groups={"test"}) + * @Assert\Range(min=1, max=100) + */ + public $property; + + /** + * @var int + * + * @Assert\Range(min=1, max=100) + */ + public $propertyInDefaultGroup; + + /** + * @var array + * + * @OA\Property(type="array", @OA\Items(type="string")) + * @Assert\Valid + */ + public $propertyArray; + } +} else { + class SymfonyConstraintsWithValidationGroups + { + /** + * @var int + */ + #[Assert\Range(min: 1, max: 100)] + #[Assert\NotBlank(groups: ["test"])] + #[Groups("test")] + public $property; + + /** + * @var int + */ + #[Assert\Range(min: 1, max: 100)] + public $propertyInDefaultGroup; + + /** + * @var array + */ + #[Property(type: 'array', items: new Items(type: 'string'))] + #[Assert\Valid] + public $propertyArray; + } } diff --git a/Tests/Functional/Entity/SymfonyDiscriminator.php b/Tests/Functional/Entity/SymfonyDiscriminator.php index cd4e562ad..4341b6159 100644 --- a/Tests/Functional/Entity/SymfonyDiscriminator.php +++ b/Tests/Functional/Entity/SymfonyDiscriminator.php @@ -11,18 +11,33 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; -/** - * @DiscriminatorMap(typeProperty="type", mapping={ - * "one": SymfonyDiscriminatorOne::class, - * "two": SymfonyDiscriminatorTwo::class, - * }) - */ -abstract class SymfonyDiscriminator -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @var string + * @DiscriminatorMap(typeProperty="type", mapping={ + * "one": SymfonyDiscriminatorOne::class, + * "two": SymfonyDiscriminatorTwo::class, + * }) */ - public $type; + abstract class SymfonyDiscriminator + { + /** + * @var string + */ + public $type; + } +} else { + #[DiscriminatorMap( + typeProperty: 'type', + mapping: ['one' => SymfonyDiscriminatorOne::class, 'two' => SymfonyDiscriminatorTwo::class] + )] + abstract class SymfonyDiscriminator + { + /** + * @var string + */ + public $type; + } } diff --git a/Tests/Functional/Entity/User.php b/Tests/Functional/Entity/User.php index 041838c43..c9e9b42dc 100644 --- a/Tests/Functional/Entity/User.php +++ b/Tests/Functional/Entity/User.php @@ -12,157 +12,301 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Property; +use Symfony\Component\HttpKernel\Kernel; -/** - * @author Guilhem N. - */ -class User -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @var int - * - * @OA\Property(description = "User id", readOnly = true, title = "userid", default = null) + * @author Guilhem N. */ - private $id; + class User + { + /** + * @var int + * + * @OA\Property(description = "User id", readOnly = true, title = "userid", default = null) + */ + private $id; - /** - * @OA\Property(type="string", readOnly = false) - */ - private $email; + /** + * @OA\Property(type="string", readOnly = false) + */ + private $email; - /** - * User Roles Comment. - * - * @var string[] - * - * @OA\Property( - * description = "User roles", - * title = "roles", - * example="[""ADMIN"",""SUPERUSER""]", - * default = {"user"}, - * ) - */ - private $roles; + /** + * User Roles Comment. + * + * @var string[] + * + * @OA\Property( + * description = "User roles", + * title = "roles", + * example="[""ADMIN"",""SUPERUSER""]", + * default = {"user"}, + * ) + */ + private $roles; - /** - * User Location. - * - * @OA\Property(type = "string") - */ - private $location; + /** + * User Location. + * + * @OA\Property(type = "string") + */ + private $location; - /** - * @var int - * - * @OA\Property(type = "string") - */ - private $friendsNumber; + /** + * @var int + * + * @OA\Property(type = "string") + */ + private $friendsNumber; - /** - * @var float - * @OA\Property(default = 0.0) - */ - private $money; + /** + * @var float + * @OA\Property(default = 0.0) + */ + private $money; - /** - * @var \DateTime - * @OA\Property(property="creationDate") - */ - private $createdAt; + /** + * @var \DateTime + * @OA\Property(property="creationDate") + */ + private $createdAt; - /** - * @var User[] - */ - private $users; + /** + * @var User[] + */ + private $users; - /** - * @var User|null - */ - private $friend; + /** + * @var User|null + */ + private $friend; - /** - * @var User[]|null - */ - private $friends; + /** + * @var User[]|null + */ + private $friends; - /** - * @var string - * - * @OA\Property(enum = {"disabled", "enabled"}) - */ - private $status; + /** + * @var string + * + * @OA\Property(enum = {"disabled", "enabled"}) + */ + private $status; - /** - * @var \DateTimeInterface - */ - private $dateAsInterface; + /** + * @var \DateTimeInterface + */ + private $dateAsInterface; - public function setMoney(float $money) - { - $this->money = $money; - } + public function setMoney(float $money) + { + $this->money = $money; + } - /** - * @OA\Property(example=1) - */ - public function setId(int $id) - { - $this->id = $id; - } + /** + * @OA\Property(example=1) + */ + public function setId(int $id) + { + $this->id = $id; + } - public function setEmail($email) - { - $this->email = $email; - } + public function setEmail($email) + { + $this->email = $email; + } + + /** + * @param string[] $roles + */ + public function setRoles(array $roles) + { + $this->roles = $roles; + } + + public function setLocation(string $location) + { + } + + public function setFriendsNumber(int $friendsNumber) + { + $this->friendsNumber = $friendsNumber; + } + + public function setCreatedAt(\DateTime $createAt) + { + } + + public function setUsers(array $users) + { + } + + public function setFriend(self $friend = null) + { + } + + public function setFriends(array $friends = []) + { + } + public function setDummy(Dummy $dummy) + { + } + + public function setStatus(string $status) + { + } + + public function getDateAsInterface(): \DateTimeInterface + { + return $this->dateAsInterface; + } + + public function setDateAsInterface(\DateTimeInterface $dateAsInterface) + { + $this->dateAsInterface = $dateAsInterface; + } + } +} else { /** - * @param string[] $roles + * @author Guilhem N. */ - public function setRoles(array $roles) + class User { - $this->roles = $roles; - } + /** + * @var int + */ + #[Property(description: 'User id', readOnly: true, title: 'userid', default: null)] + private $id; - public function setLocation(string $location) - { - } + #[Property(type: 'string', readOnly: false)] + private $email; - public function setFriendsNumber(int $friendsNumber) - { - $this->friendsNumber = $friendsNumber; - } + /** + * User Roles Comment. + * + * @var string[] + */ + #[Property(description: 'User roles', title: 'roles', example: ['ADMIN', 'SUPERUSER'], default: ['USER'])] + private $roles; - public function setCreatedAt(\DateTime $createAt) - { - } + /** + * User Location. + */ + #[Property(type: 'string')] + private $location; - public function setUsers(array $users) - { - } + /** + * @var int + */ + #[Property(type: 'string')] + private $friendsNumber; - public function setFriend(self $friend = null) - { - } + /** + * @var float + */ + #[Property(default: 0.0)] + private $money; - public function setFriends(array $friends = []) - { - } + /** + * @var \DateTime + */ + #[Property(property: 'creationDate')] + private $createdAt; - public function setDummy(Dummy $dummy) - { - } + /** + * @var User[] + */ + private $users; - public function setStatus(string $status) - { - } + /** + * @var User|null + */ + private $friend; - public function getDateAsInterface(): \DateTimeInterface - { - return $this->dateAsInterface; - } + /** + * @var User[]|null + */ + private $friends; - public function setDateAsInterface(\DateTimeInterface $dateAsInterface) - { - $this->dateAsInterface = $dateAsInterface; + /** + * @var string + */ + #[Property(enum: ['disabled', 'enabled'])] + private $status; + + /** + * @var \DateTimeInterface + */ + private $dateAsInterface; + + public function setMoney(float $money) + { + $this->money = $money; + } + + #[Property(example: 1)] + public function setId(int $id) + { + $this->id = $id; + } + + public function setEmail($email) + { + $this->email = $email; + } + + /** + * @param string[] $roles + */ + public function setRoles(array $roles) + { + $this->roles = $roles; + } + + public function setLocation(string $location) + { + } + + public function setFriendsNumber(int $friendsNumber) + { + $this->friendsNumber = $friendsNumber; + } + + public function setCreatedAt(\DateTime $createAt) + { + } + + public function setUsers(array $users) + { + } + + public function setFriend(self $friend = null) + { + } + + public function setFriends(array $friends = []) + { + } + + public function setDummy(Dummy $dummy) + { + } + + public function setStatus(string $status) + { + } + + public function getDateAsInterface(): \DateTimeInterface + { + return $this->dateAsInterface; + } + + public function setDateAsInterface(\DateTimeInterface $dateAsInterface) + { + $this->dateAsInterface = $dateAsInterface; + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php b/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php new file mode 100644 index 000000000..6cf7d4f16 --- /dev/null +++ b/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php @@ -0,0 +1,34 @@ + + */ +class SerializedNameEntity +{ + /** + * @var string + */ + #[SerializedName("notfoo")] + public $foo; + + /** + * Tests serialized name feature. + */ + #[SerializedName("notwhatyouthink")] + public function setBar(string $bar) + { + } +} diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index b500512ec..561c21108 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -13,11 +13,16 @@ use OpenApi\Annotations as OA; use OpenApi\Generator; +use Symfony\Component\HttpKernel\Kernel; class FOSRestTest extends WebTestCase { protected function setUp(): void { + if (Kernel::MAJOR_VERSION < 7) { + $this->markTestSkipped('Not supported in symfony 7'); + } + parent::setUp(); static::createClient([], ['HTTP_HOST' => 'api.example.com']); diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index 7c9bb784d..7a3498b66 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -11,11 +11,13 @@ namespace Nelmio\ApiDocBundle\Tests\Functional; +use Doctrine\Common\Annotations\Reader; use Nelmio\ApiDocBundle\OpenApiPhp\Util; use Nelmio\ApiDocBundle\Tests\Helper; use OpenApi\Annotations as OAAnnotations; use OpenApi\Attributes as OAAttributes; use OpenApi\Generator; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\SerializedName; class FunctionalTest extends WebTestCase @@ -62,7 +64,9 @@ public function testFetchArticleAction(string $articleRoute) public function provideArticleRoute(): iterable { - yield 'Annotations' => ['/api/article/{id}']; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => ['/api/article/{id}']; + } if (\PHP_VERSION_ID >= 80100) { yield 'Attributes' => ['/api/article_attributes/{id}']; diff --git a/Tests/Functional/Resources/routes-attributes.yaml b/Tests/Functional/Resources/routes-attributes.yaml new file mode 100644 index 000000000..eab7d3a37 --- /dev/null +++ b/Tests/Functional/Resources/routes-attributes.yaml @@ -0,0 +1,40 @@ +# Resources +test: + resource: ../Controller/TestController.php + type: attribute + +api: + resource: ../Controller/ApiController.php + type: attribute + +class_api: + resource: ../Controller/ClassApiController.php + type: attribute + +undocumented: + resource: ../Controller/UndocumentedController.php + type: attribute + +invokable: + resource: ../Controller/InvokableController.php + type: attribute + +api_platform: + resource: . + prefix: /api + type: api_platform + +# Controllers +doc_area: + path: /{area}/docs + controller: nelmio_api_doc.controller.swagger_ui + defaults: + area: default + +doc_json: + path: /{area}/docs.json + controller: nelmio_api_doc.controller.swagger_json + +doc_yaml: + path: /{area}/docs.yaml + controller: nelmio_api_doc.controller.swagger_yaml \ No newline at end of file diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index d2aa13978..237f0790c 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -46,6 +46,8 @@ class TestKernel extends Kernel private $flags; + private bool $supportsLegacyAnnotations; + public function __construct(int $flags = 0) { parent::__construct('test'.$flags, true); @@ -61,18 +63,21 @@ public function registerBundles(): iterable $bundles = [ new FrameworkBundle(), new TwigBundle(), - new SensioFrameworkExtraBundle(), new ApiPlatformBundle(), new NelmioApiDocBundle(), new TestBundle(), - new FOSRestBundle(), ]; - if ($this->flags & self::USE_JMS) { - $bundles[] = new JMSSerializerBundle(); + if (self::MAJOR_VERSION < 7) { + $bundles[] = new SensioFrameworkExtraBundle(); + $bundles[] = new FOSRestBundle(); - if ($this->flags & self::USE_BAZINGA) { - $bundles[] = new BazingaHateoasBundle(); + if ($this->flags & self::USE_JMS) { + $bundles[] = new JMSSerializerBundle(); + + if ($this->flags & self::USE_BAZINGA) { + $bundles[] = new BazingaHateoasBundle(); + } } } @@ -84,28 +89,34 @@ public function registerBundles(): iterable */ protected function configureRoutes($routes) { - $this->import($routes, __DIR__.'/Resources/routes.yaml', '/', 'yaml'); + if (self::MAJOR_VERSION < 7) { + $this->import($routes, __DIR__.'/Resources/routes.yaml', '/', 'yaml'); + } else { + $this->import($routes, __DIR__.'/Resources/routes-attributes.yaml', '/', 'yaml'); + } if (class_exists(SerializedName::class)) { - $this->import($routes, __DIR__.'/Controller/SerializedNameController.php', '/', 'annotation'); + $this->import($routes, __DIR__.'/Controller/SerializedNameController.php', '/', self::MAJOR_VERSION < 7 ? 'annotation' : 'attribute'); } - if ($this->flags & self::USE_JMS) { - $this->import($routes, __DIR__.'/Controller/JMSController.php', '/', 'annotation'); - } + if (self::MAJOR_VERSION < 7) { + if ($this->flags & self::USE_JMS) { + $this->import($routes, __DIR__.'/Controller/JMSController.php', '/', 'annotation'); + } - if ($this->flags & self::USE_BAZINGA) { - $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', 'annotation'); + if ($this->flags & self::USE_BAZINGA) { + $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', 'annotation'); - try { - new \ReflectionMethod(Embedded::class, 'getType'); - $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', 'annotation'); - } catch (\ReflectionException $e) { + try { + new \ReflectionMethod(Embedded::class, 'getType'); + $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', 'annotation'); + } catch (\ReflectionException $e) { + } } - } - if ($this->flags & self::ERROR_ARRAY_ITEMS) { - $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', 'annotation'); + if ($this->flags & self::ERROR_ARRAY_ITEMS) { + $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', 'annotation'); + } } } @@ -132,8 +143,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'test' => null, 'validation' => null, 'form' => null, - 'serializer' => [ - 'enable_annotations' => true, + 'serializer' => self::MAJOR_VERSION < 7 ? ['enable_annotations' => true] : [] + [ 'mapping' => [ 'paths' => [__DIR__.'/Resources/serializer/'], ], @@ -156,12 +166,15 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'strict_variables' => '%kernel.debug%', 'exception_controller' => null, ]); + + if (self::MAJOR_VERSION < 7) { + $c->loadFromExtension('sensio_framework_extra', [ + 'router' => [ + 'annotations' => false, + ], + ]); + } - $c->loadFromExtension('sensio_framework_extra', [ - 'router' => [ - 'annotations' => false, - ], - ]); $c->loadFromExtension('api_platform', [ 'mapping' => ['paths' => [ @@ -171,28 +184,77 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ]], ]); - $c->loadFromExtension('fos_rest', [ - 'format_listener' => [ - 'rules' => [ - [ - 'path' => '^/', - 'fallback_format' => 'json', + if (self::MAJOR_VERSION < 7) { + $c->loadFromExtension('fos_rest', [ + 'format_listener' => [ + 'rules' => [ + [ + 'path' => '^/', + 'fallback_format' => 'json', + ], ], ], + ]); + + // If FOSRestBundle 2.8 + if (class_exists(\FOS\RestBundle\EventListener\ResponseStatusCodeListener::class)) { + $c->loadFromExtension('fos_rest', [ + 'exception' => [ + 'enabled' => false, + 'exception_listener' => false, + 'serialize_exceptions' => false, + ], + 'body_listener' => false, + 'routing_loader' => false, + ]); + } + } + + $models = [ + [ + 'alias' => 'PrivateProtectedExposure', + 'type' => PrivateProtectedExposure::class, ], - ]); + [ + 'alias' => 'SymfonyConstraintsTestGroup', + 'type' => SymfonyConstraintsWithValidationGroups::class, + 'groups' => ['test'], + ], + [ + 'alias' => 'SymfonyConstraintsDefaultGroup', + 'type' => SymfonyConstraintsWithValidationGroups::class, + 'groups' => null, + ], + ]; - // If FOSRestBundle 2.8 - if (class_exists(\FOS\RestBundle\EventListener\ResponseStatusCodeListener::class)) { - $c->loadFromExtension('fos_rest', [ - 'exception' => [ - 'enabled' => false, - 'exception_listener' => false, - 'serialize_exceptions' => false, + if (self::MAJOR_VERSION < 7) { + $models = [ + ...$models, + [ + 'alias' => 'JMSPicture_mini', + 'type' => JMSPicture::class, + 'groups' => ['mini'], ], - 'body_listener' => false, - 'routing_loader' => false, - ]); + [ + 'alias' => 'BazingaUser_grouped', + 'type' => BazingaUser::class, + 'groups' => ['foo'], + ], + [ + 'alias' => 'JMSComplex', + 'type' => JMSComplex::class, + 'groups' => [ + 'list', + 'details', + 'User' => ['list'], + ], + ], + [ + 'alias' => 'JMSComplexDefault', + 'type' => JMSComplex::class, + 'groups' => null, + ], + ]; } // Filter routes @@ -267,46 +329,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], ], 'models' => [ - 'names' => [ - [ - 'alias' => 'PrivateProtectedExposure', - 'type' => PrivateProtectedExposure::class, - ], - [ - 'alias' => 'JMSPicture_mini', - 'type' => JMSPicture::class, - 'groups' => ['mini'], - ], - [ - 'alias' => 'BazingaUser_grouped', - 'type' => BazingaUser::class, - 'groups' => ['foo'], - ], - [ - 'alias' => 'JMSComplex', - 'type' => JMSComplex::class, - 'groups' => [ - 'list', - 'details', - 'User' => ['list'], - ], - ], - [ - 'alias' => 'JMSComplexDefault', - 'type' => JMSComplex::class, - 'groups' => null, - ], - [ - 'alias' => 'SymfonyConstraintsTestGroup', - 'type' => SymfonyConstraintsWithValidationGroups::class, - 'groups' => ['test'], - ], - [ - 'alias' => 'SymfonyConstraintsDefaultGroup', - 'type' => SymfonyConstraintsWithValidationGroups::class, - 'groups' => null, - ], - ], + 'names' => $models, ], ]); diff --git a/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php index b84d27944..e9b42fe45 100644 --- a/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php @@ -38,7 +38,11 @@ public function testProperty($entity) $schema->merge([new OA\Property(['property' => 'property2'] + $baseProps)]); $registry = new ModelRegistry([], new OA\OpenApi($baseProps), []); - $symfonyConstraintAnnotationReader = new OpenApiAnnotationsReader(new AnnotationReader(), $registry, ['json']); + $symfonyConstraintAnnotationReader = new OpenApiAnnotationsReader( + class_exists(AnnotationReader::class) ? new AnnotationReader() : null, + $registry, + ['json'] + ); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property2'), $schema->properties[1]); diff --git a/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php b/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php index bbfb42019..e6b5d3f74 100644 --- a/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php +++ b/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php @@ -14,6 +14,7 @@ class_alias(CompoundStub::class, Compound::class); /** * @Annotation */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] final class CompoundValidationRule extends Compound { protected function getConstraints(array $options): array diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index 14a00741c..4e155cd76 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -16,6 +16,8 @@ use Nelmio\ApiDocBundle\Tests\Helper; use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert; use OpenApi\Annotations as OA; +use OpenApi\Attributes\Property; +use OpenApi\Attributes\Schema; use OpenApi\Context; use OpenApi\Generator; use PHPUnit\Framework\TestCase; @@ -24,6 +26,16 @@ class SymfonyConstraintAnnotationReaderTest extends TestCase { + /** + * @var AnnotationReader|null + */ + private $doctrineAnnotations; + + protected function setUp(): void + { + $this->doctrineAnnotations = class_exists(AnnotationReader::class) ? new AnnotationReader() : null; + } + public function testUpdatePropertyFix1283() { $entity = new class() { @@ -42,7 +54,7 @@ public function testUpdatePropertyFix1283() $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property2'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -66,7 +78,7 @@ public function testOptionalProperty($entity) $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property2'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -110,7 +122,7 @@ public function testAssertChoiceResultsInNumericArray($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -152,7 +164,7 @@ public function testMultipleChoiceConstraintsApplyEnumToItems($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -188,7 +200,7 @@ public function testLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -224,7 +236,7 @@ public function testLengthConstraintDoesNotSetMinLengthIfMinIsNotSet($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -263,7 +275,7 @@ public function testCompoundValidationRules() $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => $propertyName])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, $propertyName), $schema->properties[0]); @@ -293,7 +305,7 @@ public function testCountConstraintDoesNotSetMinItemsIfMinIsNotSet($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -329,7 +341,7 @@ public function testCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -365,7 +377,7 @@ public function testRangeConstraintDoesNotSetMaximumIfMaxIsNotSet($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -401,7 +413,7 @@ public function testRangeConstraintDoesNotSetMinimumIfMinIsNotSet($entity) $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); - $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader(new AnnotationReader()); + $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); @@ -479,9 +491,9 @@ public function testReaderWithValidationGroupsEnabledDoesNotReadAnnotationsWitho */ public function testReaderWithValidationGroupsEnabledReadsOnlyConstraintsWithGroupsProvided($entity) { - $schema = $this->createObj(OA\Schema::class, []); + $schema = $this->createObj(Schema::class, []); $schema->merge([ - $this->createObj(OA\Property::class, ['property' => 'property1']), + $this->createObj(Property::class, ['property' => 'property1']), ]); $reader = $this->createConstraintReaderWithValidationGroupsEnabled(); $reader->setSchema($schema); @@ -543,7 +555,7 @@ public function provideConstraintsWithGroups(): iterable private function createConstraintReaderWithValidationGroupsEnabled(): SymfonyConstraintAnnotationReader { return new SymfonyConstraintAnnotationReader( - new AnnotationReader(), + $this->doctrineAnnotations, true ); } diff --git a/Tests/RouteDescriber/FosRestDescriberTest.php b/Tests/RouteDescriber/FosRestDescriberTest.php index 6219d718b..5d94b7b42 100644 --- a/Tests/RouteDescriber/FosRestDescriberTest.php +++ b/Tests/RouteDescriber/FosRestDescriberTest.php @@ -16,6 +16,7 @@ use Nelmio\ApiDocBundle\RouteDescriber\FosRestDescriber; use OpenApi\Annotations\OpenApi; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Route; use Symfony\Component\Validator\Constraints\Choice; @@ -23,15 +24,22 @@ class FosRestDescriberTest extends TestCase { public function testQueryParamWithChoiceConstraintIsAddedAsEnum() { + if (Kernel::MAJOR_VERSION >= 7) { + $this->markTestSkipped('FosRest is not supported in symfony 7'); + } + $choices = ['foo', 'bar']; $queryParam = new QueryParam(); $queryParam->requirements = new Choice($choices); - $readerMock = $this->createMock(Reader::class); - $readerMock->method('getMethodAnnotations')->willReturn([ - $queryParam, - ]); + $readerMock = null; + if (interface_exists(Reader::class)) { + $readerMock = $this->createMock(Reader::class); + $readerMock->method('getMethodAnnotations')->willReturn([ + $queryParam, + ]); + } $fosRestDescriber = new FosRestDescriber($readerMock, []); $api = new OpenApi([]); diff --git a/Tests/Routing/FilteredRouteCollectionBuilderTest.php b/Tests/Routing/FilteredRouteCollectionBuilderTest.php index f9eec1d6a..32cc91a98 100644 --- a/Tests/Routing/FilteredRouteCollectionBuilderTest.php +++ b/Tests/Routing/FilteredRouteCollectionBuilderTest.php @@ -31,6 +31,16 @@ */ class FilteredRouteCollectionBuilderTest extends TestCase { + /** + * @var AnnotationReader|null + */ + private $doctrineAnnotations; + + protected function setUp(): void + { + $this->doctrineAnnotations = class_exists(AnnotationReader::class) ? new AnnotationReader() : null; + } + public function testFilter() { $options = [ @@ -50,7 +60,7 @@ public function testFilter() } $routeBuilder = new FilteredRouteCollectionBuilder( - new AnnotationReader(), + $this->doctrineAnnotations, $this->createControllerReflector(), 'areaName', $options @@ -77,7 +87,7 @@ public function testFilterWithDeprecatedArgument() } $routeBuilder = new FilteredRouteCollectionBuilder( - new AnnotationReader(), + $this->doctrineAnnotations, $this->createControllerReflector(), 'areaName', $pathPattern @@ -95,7 +105,7 @@ public function testFilterWithInvalidOption(array $options) $this->expectException(InvalidArgumentException::class); new FilteredRouteCollectionBuilder( - new AnnotationReader(), + $this->doctrineAnnotations, $this->createControllerReflector(), 'areaName', $options @@ -148,7 +158,7 @@ public function testMatchingRoutes(string $name, Route $route, array $options = $routes->add($name, $route); $routeBuilder = new FilteredRouteCollectionBuilder( - new AnnotationReader(), + $this->doctrineAnnotations, $this->createControllerReflector(), 'area', $options @@ -188,12 +198,15 @@ public function testMatchingRoutesWithAnnotation(string $name, Route $route, arr $controllerReflectorStub = $this->createMock(ControllerReflector::class); $controllerReflectorStub->method('getReflectionMethod')->willReturn($reflectionMethodStub); - $annotationReader = $this->createMock(Reader::class); - $annotationReader - ->method('getMethodAnnotation') - ->with($reflectionMethodStub, Areas::class) - ->willReturn(new Areas(['value' => [$area]])) - ; + $annotationReader = null; + if (interface_exists(Reader::class)) { + $annotationReader = $this->createMock(Reader::class); + $annotationReader + ->method('getMethodAnnotation') + ->with($reflectionMethodStub, Areas::class) + ->willReturn(new Areas(['value' => [$area]])) + ; + } $routeBuilder = new FilteredRouteCollectionBuilder( $annotationReader, @@ -246,7 +259,7 @@ public function testNonMatchingRoutes(string $name, Route $route, array $options $routes->add($name, $route); $routeBuilder = new FilteredRouteCollectionBuilder( - new AnnotationReader(), + $this->doctrineAnnotations, $this->createControllerReflector(), 'areaName', $options @@ -289,11 +302,14 @@ public function testRoutesWithDisabledDefaultRoutes( $controllerReflectorStub = $this->createMock(ControllerReflector::class); $controllerReflectorStub->method('getReflectionMethod')->willReturn($reflectionMethodStub); - $annotationReader = $this->createMock(Reader::class); - $annotationReader - ->method('getMethodAnnotations') - ->willReturn($annotations) - ; + $annotationReader = null; + if (interface_exists(Reader::class)) { + $annotationReader = $this->createMock(Reader::class); + $annotationReader + ->method('getMethodAnnotations') + ->willReturn($annotations) + ; + } $routeBuilder = new FilteredRouteCollectionBuilder( $annotationReader, diff --git a/composer.json b/composer.json index e332fa6bb..f6425bd12 100644 --- a/composer.json +++ b/composer.json @@ -17,40 +17,38 @@ "require": { "php": ">=7.2", "ext-json": "*", - "doctrine/annotations": "^2.0", "psr/cache": "^1.0|^2.0|^3.0", "psr/container": "^1.0|^2.0", "psr/log": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4.24|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/options-resolver": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4.24|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/options-resolver": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", "zircote/swagger-php": "^4.2.15", "phpdocumentor/reflection-docblock": "^3.1|^4.0|^5.0" }, "require-dev": { "sensio/framework-extra-bundle": "^5.4|^6.0", - "symfony/asset": "^5.4|^6.0", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/cache": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", "symfony/phpunit-bridge": "^6.3.2", - "symfony/property-access": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/templating": "^5.4|^6.0", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/validator": "^5.4|^6.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/templating": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/validator": "^5.4|^6.0|^7.0", "api-platform/core": "^2.7.0|^3", "symfony/deprecation-contracts": "^2.1|^3", - "friendsofsymfony/rest-bundle": "^2.8|^3.0", "willdurand/hateoas-bundle": "^1.0|^2.0", "jms/serializer-bundle": "^2.3|^3.0|^4.0|^5.0@beta", @@ -59,6 +57,7 @@ }, "suggest": { "api-platform/core": "For using an API oriented framework.", + "doctrine/annotations": "For using doctrine annotations", "friendsofsymfony/rest-bundle": "For using the parameters annotations.", "jms/serializer-bundle": "For describing your models.", "symfony/asset": "For using the Swagger UI.", From 3b35a25871d92e42f1425e52b14989326b3d1533 Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Mon, 11 Dec 2023 12:13:38 +0100 Subject: [PATCH 02/54] cs-fix --- Tests/Functional/Controller/ApiController.php | 2 +- .../Functional/Controller/ApiController80.php | 58 +++++++++++++++++++ .../Controller/ArrayItemsErrorController.php | 2 + .../Controller/BazingaController.php | 4 ++ .../Controller/BazingaTypedController.php | 2 + .../Controller/ClassApiController.php | 8 ++- .../Controller/FOSRestController80.php | 2 + .../Controller/InvokableController.php | 5 +- Tests/Functional/Controller/JMSController.php | 18 ++++++ .../Controller/SerializedNameController.php | 8 ++- .../Functional/Controller/TestController.php | 5 +- .../Controller/UndocumentedController.php | 8 +-- Tests/Functional/Entity/Article.php | 3 +- Tests/Functional/Entity/CustomDateTime.php | 2 + .../Entity/EntityWithAlternateType.php | 14 ++--- .../Entity/EntityWithObjectType.php | 1 - Tests/Functional/Entity/JMSComplex.php | 12 ++++ .../Entity/JMSNamingStrategyConstraints.php | 3 + Tests/Functional/Entity/JMSNote.php | 2 + Tests/Functional/Entity/JMSUser.php | 32 ++++++++++ .../Functional/Entity/NestedGroup/JMSChat.php | 2 + .../Entity/NestedGroup/JMSChatFriend.php | 5 ++ .../Entity/NestedGroup/JMSChatLivingRoom.php | 1 + .../Entity/NestedGroup/JMSChatRoom.php | 5 ++ .../Entity/NestedGroup/JMSChatRoomUser.php | 3 + .../Entity/NestedGroup/JMSChatUser.php | 4 ++ .../Entity/NestedGroup/JMSPicture.php | 3 + .../Functional/Entity/SymfonyConstraints.php | 24 ++++---- ...SymfonyConstraintsWithValidationGroups.php | 7 ++- Tests/Functional/Entity/User.php | 4 +- Tests/Functional/Entity/VirtualProperty.php | 5 ++ .../EntityExcluded/ApiPlatform2/Dummy.php | 1 + .../Symfony7/SerializedNameEntity.php | 4 +- Tests/Functional/TestKernel.php | 27 ++------- Tests/Functional/WebTestCase.php | 1 - Tests/Model/ModelRegistryTest.php | 2 - .../Annotations/AnnotationReaderTest.php | 1 + .../SymfonyConstraintAnnotationReaderTest.php | 23 ++++++++ .../ApplyOpenApiDiscriminatorTraitTest.php | 4 +- Tests/Render/RenderOpenApiTest.php | 5 +- .../FilteredRouteCollectionBuilderTest.php | 2 + Tests/Util/ControllerReflectorTest.php | 5 +- 42 files changed, 250 insertions(+), 79 deletions(-) diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index 0dbf4efb3..798d2a286 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -15,7 +15,7 @@ use Symfony\Component\Routing\Annotation\Route; if (Kernel::MAJOR_VERSION >= 7) { - #[Route("/api", name: 'api_', host: 'api.example.com')] + #[Route('/api', name: 'api_', host: 'api.example.com')] class ApiController extends ApiController81 { } diff --git a/Tests/Functional/Controller/ApiController80.php b/Tests/Functional/Controller/ApiController80.php index a570ebf53..423aff1fd 100644 --- a/Tests/Functional/Controller/ApiController80.php +++ b/Tests/Functional/Controller/ApiController80.php @@ -39,14 +39,19 @@ class ApiController80 { /** * @OA\Get( + * * @OA\Response( * response="200", * description="Success", + * * @Model(type=Article::class, groups={"light"})) * ) * ) + * * @OA\Parameter(ref="#/components/parameters/test") + * * @Route("/article/{id}", methods={"GET"}) + * * @OA\Parameter(name="Accept-Version", in="header", @OA\Schema(type="string")) * @OA\Parameter(name="Application-Name", in="header", @OA\Schema(type="string")) */ @@ -56,14 +61,19 @@ public function fetchArticleAction() /** * @OA\Get( + * * @OA\Response( * response="200", * description="Success", + * * @Model(type=ArticleInterface::class, groups={"light"})) * ) * ) + * * @OA\Parameter(ref="#/components/parameters/test") + * * @Route("/article-interface/{id}", methods={"GET"}) + * * @OA\Parameter(name="Accept-Version", in="header", @OA\Schema(type="string")) * @OA\Parameter(name="Application-Name", in="header", @OA\Schema(type="string")) */ @@ -76,15 +86,21 @@ public function fetchArticleInterfaceAction() * * @Route("/swagger", methods={"GET", "LINK"}) * @Route("/swagger2", methods={"GET"}) + * * @Operation( + * * @OA\Response(response="201", description="An example resource") * ) + * * @OA\Get( * path="/api/swagger2", + * * @OA\Parameter(name="Accept-Version", in="header", @OA\Schema(type="string")) * ) + * * @OA\Post( * path="/api/swagger2", + * * @OA\Response(response="203", description="but 203 is not actually allowed (wrong method)") * ) */ @@ -94,18 +110,24 @@ public function swaggerAction() /** * @Route("/swagger/implicit", methods={"GET", "POST"}) + * * @OA\Response( * response="201", * description="Operation automatically detected", + * * @Model(type=User::class) * ), + * * @OA\RequestBody( * description="This is a request body", + * * @OA\JsonContent( * type="array", + * * @OA\Items(ref=@Model(type=User::class)) * ) * ) + * * @OA\Tag(name="implicit") */ public function implicitSwaggerAction() @@ -114,13 +136,17 @@ public function implicitSwaggerAction() /** * @Route("/test/users/{user}", methods={"POST"}, schemes={"https"}, requirements={"user"="/foo/"}) + * * @OA\Response( * response="201", * description="Operation automatically detected", + * * @Model(type=User::class) * ), + * * @OA\RequestBody( * description="This is a request body", + * * @Model(type=UserType::class, options={"bar": "baz"})) * ) */ @@ -130,6 +156,7 @@ public function submitUserTypeAction() /** * @Route("/test/{user}", methods={"GET"}, schemes={"https"}, requirements={"user"="/foo/"}) + * * @OA\Response(response=200, description="sucessful") */ public function userAction() @@ -161,6 +188,7 @@ public function adminAction() /** * @OA\Get( * path="/filtered", + * * @OA\Response(response="201", description="") * ) */ @@ -170,10 +198,13 @@ public function filteredAction() /** * @Route("/form", methods={"POST"}) + * * @OA\RequestBody( * description="Request content", + * * @Model(type=DummyType::class)) * ) + * * @OA\Response(response="201", description="") */ public function formAction() @@ -182,10 +213,13 @@ public function formAction() /** * @Route("/form-model", methods={"POST"}) + * * @OA\RequestBody( * description="Request content", + * * @Model(type=FormWithModel::class)) * ) + * * @OA\Response(response="201", description="") */ public function formWithModelAction() @@ -194,7 +228,9 @@ public function formWithModelAction() /** * @Route("/security") + * * @OA\Response(response="201", description="") + * * @Security(name="api_key") * @Security(name="basic") * @Security(name="oauth2", scopes={"scope_1"}) @@ -205,7 +241,9 @@ public function securityAction() /** * @Route("/securityOverride") + * * @OA\Response(response="201", description="") + * * @Security(name="api_key") * @Security(name=null) */ @@ -215,9 +253,11 @@ public function securityActionOverride() /** * @Route("/swagger/symfonyConstraints", methods={"GET"}) + * * @OA\Response( * response="201", * description="Used for symfony constraints test", + * * @Model(type=SymfonyConstraints::class) * ) */ @@ -235,6 +275,7 @@ public function symfonyConstraintsAction() * response="201", * ref="#/components/responses/201" * ) + * * @Route("/configReference", methods={"GET"}) */ public function configReferenceAction() @@ -243,7 +284,9 @@ public function configReferenceAction() /** * @Route("/multi-annotations", methods={"GET", "POST"}) + * * @OA\Get(description="This is the get operation") + * * @OA\Post(description="This is post") * * @OA\Response(response=200, description="Worked well!", @Model(type=DummyType::class)) @@ -301,7 +344,9 @@ public function namedRouteOperationIdAction() * @Route("/custom-operation-id", methods={"GET", "POST"}) * * @OA\Get(operationId="get-custom-operation-id") + * * @OA\Post(operationId="post-custom-operation-id") + * * @OA\Response(response=200, description="success") */ public function customOperationIdAction() @@ -310,9 +355,11 @@ public function customOperationIdAction() /** * @Route("/swagger/symfonyConstraintsWithValidationGroups", methods={"GET"}) + * * @OA\Response( * response="201", * description="Used for symfony constraints with validation groups test", + * * @Model(type=SymfonyConstraintsWithValidationGroups::class, groups={"test"}) * ) */ @@ -324,6 +371,7 @@ public function symfonyConstraintsWithGroupsAction() * @Route("/alternate-entity-type", methods={"GET", "POST"}) * * @OA\Get(operationId="alternate-entity-type") + * * @OA\Response(response=200, description="success", @OA\JsonContent( * ref=@Model(type=EntityWithAlternateType::class), * )) @@ -336,6 +384,7 @@ public function alternateEntityType() * @Route("/entity-with-ref", methods={"GET", "POST"}) * * @OA\Get(operationId="entity-with-ref") + * * @OA\Response(response=200, description="success", @OA\JsonContent( * ref=@Model(type=EntityWithRef::class), * )) @@ -348,6 +397,7 @@ public function entityWithRef() * @Route("/entity-with-object-type", methods={"GET", "POST"}) * * @OA\Get(operationId="entity-with-object-type") + * * @OA\Response(response=200, description="success", @OA\JsonContent( * ref=@Model(type=EntityWithObjectType::class), * )) @@ -358,11 +408,14 @@ public function entityWithObjectType() /** * @Route("/form-with-alternate-type", methods={"POST"}) + * * @OA\Response( * response="204", * description="Operation automatically detected", * ), + * * @OA\RequestBody( + * * @Model(type=FormWithAlternateSchemaType::class)) * ) */ @@ -372,11 +425,14 @@ public function formWithAlternateSchemaType() /** * @Route("/form-with-ref-type", methods={"POST"}) + * * @OA\Response( * response="204", * description="Operation automatically detected", * ), + * * @OA\RequestBody( + * * @Model(type=FormWithRefType::class)) * ) */ @@ -386,9 +442,11 @@ public function formWithRefSchemaType() /** * @Route("/entity-with-nullable-property-set", methods={"GET"}) + * * @OA\Response( * response="201", * description="Operation automatically detected", + * * @Model(type=EntityWithNullableSchemaSet::class) * ) */ diff --git a/Tests/Functional/Controller/ArrayItemsErrorController.php b/Tests/Functional/Controller/ArrayItemsErrorController.php index 00c5751d3..98da0cff3 100644 --- a/Tests/Functional/Controller/ArrayItemsErrorController.php +++ b/Tests/Functional/Controller/ArrayItemsErrorController.php @@ -23,9 +23,11 @@ class ArrayItemsErrorController { /** * @Route("/api/error", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=Foo::class) * ) */ diff --git a/Tests/Functional/Controller/BazingaController.php b/Tests/Functional/Controller/BazingaController.php index f8bb7d670..773605cdd 100644 --- a/Tests/Functional/Controller/BazingaController.php +++ b/Tests/Functional/Controller/BazingaController.php @@ -23,9 +23,11 @@ class BazingaController { /** * @Route("/api/bazinga", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=BazingaUser::class) * ) */ @@ -35,9 +37,11 @@ public function userAction() /** * @Route("/api/bazinga_foo", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=BazingaUser::class, groups={"foo"}) * ) */ diff --git a/Tests/Functional/Controller/BazingaTypedController.php b/Tests/Functional/Controller/BazingaTypedController.php index ad72687f3..377721ad4 100644 --- a/Tests/Functional/Controller/BazingaTypedController.php +++ b/Tests/Functional/Controller/BazingaTypedController.php @@ -23,9 +23,11 @@ class BazingaTypedController { /** * @Route("/api/bazinga_typed", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=BazingaUserTyped::class) * ) */ diff --git a/Tests/Functional/Controller/ClassApiController.php b/Tests/Functional/Controller/ClassApiController.php index a3a4b6d19..f2dc75184 100644 --- a/Tests/Functional/Controller/ClassApiController.php +++ b/Tests/Functional/Controller/ClassApiController.php @@ -20,12 +20,14 @@ if (Kernel::MAJOR_VERSION < 7) { /** * @Route("/api", host="api.example.com") + * * @Security(name="basic") */ class ClassApiController { /** * @Route("/security/class") + * * @OA\Response(response="201", description="") */ public function securityAction() @@ -34,13 +36,13 @@ public function securityAction() } } else { #[Security(name: 'basic')] - #[Route("/api", host: "api.example.com")] + #[Route('/api', host: 'api.example.com')] class ClassApiController { #[Response(response: 201, description: '')] - #[Route("/security/class")] + #[Route('/security/class')] public function securityAction() { } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/FOSRestController80.php b/Tests/Functional/Controller/FOSRestController80.php index 1e12df917..23352fa8e 100644 --- a/Tests/Functional/Controller/FOSRestController80.php +++ b/Tests/Functional/Controller/FOSRestController80.php @@ -22,8 +22,10 @@ class FOSRestController80 { /** * @Route("/fosrest.{_format}", methods={"POST"}) + * * @QueryParam(name="foo", requirements=@Regex("/^\d+$/")) * @QueryParam(name="mapped", map=true) + * * @RequestParam(name="Barraa", key="bar", requirements="\d+") * @RequestParam(name="baz", requirements=@IsTrue) * @RequestParam(name="datetime", requirements=@DateTime("Y-m-d\TH:i:sP")) diff --git a/Tests/Functional/Controller/InvokableController.php b/Tests/Functional/Controller/InvokableController.php index 86e4a9dbb..d91013a16 100644 --- a/Tests/Functional/Controller/InvokableController.php +++ b/Tests/Functional/Controller/InvokableController.php @@ -21,6 +21,7 @@ * Prevents a regression (see https://github.com/nelmio/NelmioApiDocBundle/issues/1559). * * @Route("/api/invoke", host="api.example.com", name="invokable", methods={"GET"}) + * * @OA\Response( * response=200, * description="Invokable!" @@ -37,11 +38,11 @@ public function __invoke() * Prevents a regression (see https://github.com/nelmio/NelmioApiDocBundle/issues/1559). */ #[Response(response: 200, description: 'Invokable!')] - #[Route("/api/invoke", host: "api.example.com", name: "invokable", methods: ["GET"])] + #[Route('/api/invoke', host: 'api.example.com', name: 'invokable', methods: ['GET'])] class InvokableController { public function __invoke() { } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/JMSController.php b/Tests/Functional/Controller/JMSController.php index 392eace10..2f377c7aa 100644 --- a/Tests/Functional/Controller/JMSController.php +++ b/Tests/Functional/Controller/JMSController.php @@ -31,9 +31,11 @@ class JMSController { /** * @Route("/api/jms", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSUser::class) * ) */ @@ -43,9 +45,11 @@ public function userAction() /** * @Route("/api/yaml", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=VirtualProperty::class) * ) */ @@ -55,9 +59,11 @@ public function yamlAction() /** * @Route("/api/jms_complex", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSComplex::class, groups={"list", "details", "User" : {"list"}}) * ) */ @@ -67,9 +73,11 @@ public function complexAction() /** * @Route("/api/jms_complex_dual", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSDualComplex::class, groups={"Default", "complex" : {"User" : {"details"}}}) * ) */ @@ -79,9 +87,11 @@ public function complexDualAction() /** * @Route("/api/jms_naming_strategy", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSNamingStrategyConstraints::class, groups={"Default"}) * ) */ @@ -91,9 +101,11 @@ public function namingStrategyConstraintsAction() /** * @Route("/api/jms_chat", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSChat::class, groups={"Default", "members" : {"mini"}}) * ) */ @@ -103,9 +115,11 @@ public function chatAction() /** * @Route("/api/jms_picture", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSPicture::class, groups={"mini"}) * ) */ @@ -115,9 +129,11 @@ public function pictureAction() /** * @Route("/api/jms_mini_user", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSChatUser::class, groups={"mini"}) * ) */ @@ -127,9 +143,11 @@ public function minUserAction() /** * @Route("/api/jms_mini_user_nested", methods={"GET"}) + * * @OA\Response( * response=200, * description="Success", + * * @Model(type=JMSChatRoomUser::class, groups={"mini", "friend": {"living":{"Default"}}}) * ) */ diff --git a/Tests/Functional/Controller/SerializedNameController.php b/Tests/Functional/Controller/SerializedNameController.php index dd9f3fa7b..47cf8389a 100644 --- a/Tests/Functional/Controller/SerializedNameController.php +++ b/Tests/Functional/Controller/SerializedNameController.php @@ -31,8 +31,10 @@ class SerializedNameController * @OA\Response( * response="200", * description="success", + * * @Model(type=SerializedNameEnt::class) * ) + * * @Route("/serializename", methods={"GET"}) */ public function serializedNameAction() @@ -43,13 +45,13 @@ public function serializedNameAction() /** * This controller is only loaded when SerializedName exists (sf >= 4.2). */ - #[Route("/api", host: "api.example.com")] + #[Route('/api', host: 'api.example.com')] class SerializedNameController { #[Response(response: 200, description: 'success', attachables: [new Model(type: SerializedNameEntity::class)])] - #[Route("/serializename", methods: ["GET"])] + #[Route('/serializename', methods: ['GET'])] public function serializedNameAction() { } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/TestController.php b/Tests/Functional/Controller/TestController.php index 71bd8b1e4..77f33d288 100644 --- a/Tests/Functional/Controller/TestController.php +++ b/Tests/Functional/Controller/TestController.php @@ -27,6 +27,7 @@ class TestController * response="200", * description="Test" * ) + * * @Route("/test/", methods={"GET"}) */ public function testAction() @@ -38,9 +39,9 @@ public function testAction() class TestController { #[Response(response: 200, description: 'Test')] - #[Route("/test/", methods: ["GET"])] + #[Route('/test/', methods: ['GET'])] public function testAction() { } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/UndocumentedController.php b/Tests/Functional/Controller/UndocumentedController.php index 92904cb1e..37bdcdbdc 100644 --- a/Tests/Functional/Controller/UndocumentedController.php +++ b/Tests/Functional/Controller/UndocumentedController.php @@ -14,7 +14,6 @@ use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; - if (Kernel::MAJOR_VERSION < 7) { /** * @Route(host="api.example.com") @@ -31,16 +30,15 @@ public function undocumentedAction() } } } else { - #[Route(host: "api.example.com")] + #[Route(host: 'api.example.com')] class UndocumentedController { /** * This path is excluded by the config (only /api allowed). - * */ - #[Route("/undocumented", methods: ["GET"])] + #[Route('/undocumented', methods: ['GET'])] public function undocumentedAction() { } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/Article.php b/Tests/Functional/Entity/Article.php index a67505b01..359ffc828 100644 --- a/Tests/Functional/Entity/Article.php +++ b/Tests/Functional/Entity/Article.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use Doctrine\Common\Annotations\AnnotationReader; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\Groups; @@ -35,7 +34,7 @@ public function setContent(string $content) } else { class Article { - #[Groups(["light"])] + #[Groups(['light'])] public function setAuthor(User $author) { } diff --git a/Tests/Functional/Entity/CustomDateTime.php b/Tests/Functional/Entity/CustomDateTime.php index 7f027c538..09af078be 100644 --- a/Tests/Functional/Entity/CustomDateTime.php +++ b/Tests/Functional/Entity/CustomDateTime.php @@ -20,7 +20,9 @@ class CustomDateTime extends \DateTime { /** * @Serializer\Type("string") + * * @Serializer\Expose + * * @Serializer\SerializedName("format") */ private $format; diff --git a/Tests/Functional/Entity/EntityWithAlternateType.php b/Tests/Functional/Entity/EntityWithAlternateType.php index 9f5c03afd..eaf1aa20d 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType.php +++ b/Tests/Functional/Entity/EntityWithAlternateType.php @@ -11,8 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use ArrayIterator; -use IteratorAggregate; use OpenApi\Annotations as OA; use OpenApi\Attributes\Items; use OpenApi\Attributes\Schema; @@ -22,16 +20,16 @@ /** * @OA\Schema(type="array", @OA\Items(type="string")) */ - class EntityWithAlternateType implements IteratorAggregate + class EntityWithAlternateType implements \IteratorAggregate { /** * @var string */ public $ignored = 'this property should be ignored because of the annotation above'; - public function getIterator(): ArrayIterator + public function getIterator(): \ArrayIterator { - return new ArrayIterator([ + return new \ArrayIterator([ 'abc', 'def', ]); @@ -39,16 +37,16 @@ public function getIterator(): ArrayIterator } } else { #[Schema(type: 'array', items: new Items(type: 'string'))] - class EntityWithAlternateType implements IteratorAggregate + class EntityWithAlternateType implements \IteratorAggregate { /** * @var string */ public $ignored = 'this property should be ignored because of the annotation above'; - public function getIterator(): ArrayIterator + public function getIterator(): \ArrayIterator { - return new ArrayIterator([ + return new \ArrayIterator([ 'abc', 'def', ]); diff --git a/Tests/Functional/Entity/EntityWithObjectType.php b/Tests/Functional/Entity/EntityWithObjectType.php index 1d17f8cdb..00235ab77 100644 --- a/Tests/Functional/Entity/EntityWithObjectType.php +++ b/Tests/Functional/Entity/EntityWithObjectType.php @@ -15,7 +15,6 @@ use OpenApi\Attributes\Schema; use Symfony\Component\HttpKernel\Kernel; - if (Kernel::MAJOR_VERSION < 7) { /** * @OA\Schema(type="object") diff --git a/Tests/Functional/Entity/JMSComplex.php b/Tests/Functional/Entity/JMSComplex.php index 5cfcbba99..fcc7d199f 100644 --- a/Tests/Functional/Entity/JMSComplex.php +++ b/Tests/Functional/Entity/JMSComplex.php @@ -17,8 +17,10 @@ /** * @Serializer\ExclusionPolicy("all") + * * @OA\Schema( * required={"id", "user"}, + * * @OA\Property(property="virtual", ref=@Model(type=JMSUser::class)) * ) */ @@ -26,30 +28,40 @@ class JMSComplex { /** * @Serializer\Type("integer") + * * @Serializer\Expose + * * @Serializer\Groups({"list"}) */ private $id; /** * @OA\Property(ref=@Model(type=JMSUser::class)) + * * @Serializer\Expose + * * @Serializer\Groups({"details"}) + * * @Serializer\SerializedName("user") */ private $User; /** * @Serializer\Type("string") + * * @Serializer\Expose + * * @Serializer\Groups({"list"}) */ private $name; /** * @Serializer\VirtualProperty + * * @Serializer\Expose + * * @Serializer\Groups({"list"}) + * * @OA\Property(ref=@Model(type=JMSUser::class)) */ public function getVirtualFriend() diff --git a/Tests/Functional/Entity/JMSNamingStrategyConstraints.php b/Tests/Functional/Entity/JMSNamingStrategyConstraints.php index 1103e20eb..ca808ed7b 100644 --- a/Tests/Functional/Entity/JMSNamingStrategyConstraints.php +++ b/Tests/Functional/Entity/JMSNamingStrategyConstraints.php @@ -20,10 +20,13 @@ class JMSNamingStrategyConstraints * @var string * * @Serializer\Type("string") + * * @Serializer\SerializedName("beautifulName") * * @Assert\NotBlank() + * * @Assert\Regex(pattern="\w+") + * * @Assert\Length(min="3", max="10") */ private $some_weird_named_property = 'default'; diff --git a/Tests/Functional/Entity/JMSNote.php b/Tests/Functional/Entity/JMSNote.php index c2118f4d8..1ec6abb3c 100644 --- a/Tests/Functional/Entity/JMSNote.php +++ b/Tests/Functional/Entity/JMSNote.php @@ -22,12 +22,14 @@ class JMSNote { /** * @Serializer\Type("string") + * * @Serializer\Expose */ private $long; /** * @Serializer\Type("int") + * * @Serializer\Expose */ private $short; diff --git a/Tests/Functional/Entity/JMSUser.php b/Tests/Functional/Entity/JMSUser.php index 7189ac5c2..438124b78 100644 --- a/Tests/Functional/Entity/JMSUser.php +++ b/Tests/Functional/Entity/JMSUser.php @@ -23,7 +23,9 @@ class JMSUser { /** * @Serializer\Type("integer") + * * @Serializer\Expose + * * @Serializer\Groups({"list"}) * * @OA\Property(description = "User id", readOnly = true, title = "userid", example=1, default = null) @@ -32,7 +34,9 @@ class JMSUser /** * @Serializer\Type("int") + * * @Serializer\Expose + * * @Serializer\SerializedName("daysOnline") * * @OA\Property(default = 0, minimum = 1, maximum = 300) @@ -41,8 +45,11 @@ class JMSUser /** * @Serializer\Type("string") + * * @Serializer\Expose + * * @OA\Property(readOnly = false) + * * @Serializer\Groups({"details"}) */ private $email; @@ -53,7 +60,9 @@ class JMSUser * @var string[] * * @Serializer\Type("array") + * * @Serializer\Accessor(getter="getRoles", setter="setRoles") + * * @Serializer\Expose * * @OA\Property(default = {"user"}, description = "Roles list", example="[""ADMIN"",""SUPERUSER""]", title="roles") @@ -64,6 +73,7 @@ class JMSUser * User Location. * * @Serializer\Type("string") + * * @Serializer\Expose */ private $location; @@ -75,6 +85,7 @@ class JMSUser /** * @OA\Property(property="last_update", type="date") + * * @Serializer\Expose */ private $updatedAt; @@ -88,31 +99,37 @@ class JMSUser /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $friends; /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $indexedFriends; /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $favoriteDates; /** * @Serializer\Type(Nelmio\ApiDocBundle\Tests\Functional\Entity\CustomDateTime::class) + * * @Serializer\Expose */ private $customDate; /** * @Serializer\Type("integer") + * * @Serializer\Expose + * * @Serializer\SerializedName("friendsNumber") * * @OA\Property(type = "string", minLength = 1, maxLength = 100) @@ -121,6 +138,7 @@ class JMSUser /** * @Serializer\Type(User::class) + * * @Serializer\Expose */ private $bestFriend; @@ -131,7 +149,9 @@ class JMSUser * Only enabled users may be used in actions. * * @var string + * * @Serializer\Type("string") + * * @Serializer\Expose * * @OA\Property(enum = {"disabled", "enabled"}) @@ -142,7 +162,9 @@ class JMSUser * JMS custom types handled via Custom Type Handlers. * * @var string + * * @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerDefined") + * * @Serializer\Expose */ private $virtualType1; @@ -151,50 +173,60 @@ class JMSUser * JMS custom types handled via Custom Type Handlers. * * @var string + * * @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerNotDefined") + * * @Serializer\Expose */ private $virtualType2; /** * @Serializer\Type("array>") + * * @Serializer\Expose */ private $latLonHistory; /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $freeFormObject; /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $freeFormObjectWithoutType; /** * @Serializer\Type("array>") + * * @Serializer\Expose */ private $deepObject; /** * @Serializer\Type("array>") + * * @Serializer\Expose */ private $deepObjectWithItems; /** * @Serializer\Type("array>>") + * * @Serializer\Expose */ private $deepFreeFormObjectCollection; /** * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNote") + * * @Serializer\Inline() + * * @Serializer\Expose */ private $notes; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChat.php b/Tests/Functional/Entity/NestedGroup/JMSChat.php index 5373464fe..a36da193f 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChat.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChat.php @@ -22,12 +22,14 @@ class JMSChat { /** * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id; /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $members; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php b/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php index 161337e79..fd0f7d3f4 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php @@ -22,20 +22,25 @@ class JMSChatFriend { /** * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatRoom") + * * @Serializer\Expose + * * @Serializer\Groups({"mini"}) */ private $room; /** * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatLivingRoom") + * * @Serializer\Expose + * * @Serializer\Groups({"Default", "mini"}) */ private $living; /** * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatRoom") + * * @Serializer\Expose */ private $dining; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatLivingRoom.php b/Tests/Functional/Entity/NestedGroup/JMSChatLivingRoom.php index c47d6df29..307f55f43 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatLivingRoom.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatLivingRoom.php @@ -22,6 +22,7 @@ class JMSChatLivingRoom { /** * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php b/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php index 76d4c43fc..f675e79e5 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php @@ -22,20 +22,25 @@ class JMSChatRoom { /** * @Serializer\Type("integer") + * * @Serializer\Expose + * * @Serializer\Groups({"Default"}) */ private $id1; /** * @Serializer\Type("integer") + * * @Serializer\Expose + * * @Serializer\Groups({"mini"}) */ private $id2; /** * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id3; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php b/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php index 8aefae3ae..c0b57cf40 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php @@ -22,13 +22,16 @@ class JMSChatRoomUser { /** * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id; /** * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatFriend") + * * @Serializer\Expose + * * @Serializer\Groups({"mini"}) */ private $friend; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatUser.php b/Tests/Functional/Entity/NestedGroup/JMSChatUser.php index a220bfd3d..d5062f62d 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatUser.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatUser.php @@ -22,19 +22,23 @@ class JMSChatUser { /** * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id; /** * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSPicture") + * * @Serializer\Groups({"mini"}) + * * @Serializer\Expose */ private $picture; /** * @Serializer\Type("array") + * * @Serializer\Expose */ private $allPictures; diff --git a/Tests/Functional/Entity/NestedGroup/JMSPicture.php b/Tests/Functional/Entity/NestedGroup/JMSPicture.php index 37650bbd6..3a2d70d5c 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSPicture.php +++ b/Tests/Functional/Entity/NestedGroup/JMSPicture.php @@ -22,13 +22,16 @@ class JMSPicture { /** * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id; /** * @Serializer\Type("integer") + * * @Serializer\Expose + * * @Serializer\Groups({"mini"}) */ private $onlyDirectPictureMini; diff --git a/Tests/Functional/Entity/SymfonyConstraints.php b/Tests/Functional/Entity/SymfonyConstraints.php index b802b460b..7a601a316 100644 --- a/Tests/Functional/Entity/SymfonyConstraints.php +++ b/Tests/Functional/Entity/SymfonyConstraints.php @@ -206,59 +206,55 @@ class SymfonyConstraints /** * @var int */ - #[Assert\NotBlank(groups: ["test"])] + #[Assert\NotBlank(groups: ['test'])] private $propertyNotBlank; /** * @var int - * */ #[Assert\NotNull()] private $propertyNotNull; /** * @var int - * */ - #[Assert\Length(min: "0", max: "50")] + #[Assert\Length(min: '0', max: '50')] private $propertyAssertLength; /** * @var int - * */ - #[Assert\Regex(pattern: "/[a-z]{2}/")] + #[Assert\Regex(pattern: '/[a-z]{2}/')] private $propertyRegex; /** * @var int - * */ - #[Assert\Count(min: "0", max: "10")] + #[Assert\Count(min: '0', max: '10')] private $propertyCount; /** * @var int */ - #[Assert\Choice(choices: ["choice1", "choice2"])] + #[Assert\Choice(choices: ['choice1', 'choice2'])] private $propertyChoice; /** * @var int */ - #[Assert\Choice(callback: [self::class, "fetchAllowedChoices"])] + #[Assert\Choice(callback: [self::class, 'fetchAllowedChoices'])] private $propertyChoiceWithCallback; /** * @var int */ - #[Assert\Choice(callback: "fetchAllowedChoices")] + #[Assert\Choice(callback: 'fetchAllowedChoices')] private $propertyChoiceWithCallbackWithoutClass; /** * @var string[] */ - #[Assert\Choice(multiple: true, choices: ["choice1", "choice2"])] + #[Assert\Choice(multiple: true, choices: ['choice1', 'choice2'])] private $propertyChoiceWithMultiple; /** @@ -266,7 +262,7 @@ class SymfonyConstraints */ #[Assert\Expression( "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", - message: "If this is a tech post, the category should be either php or symfony!" + message: 'If this is a tech post, the category should be either php or symfony!' )] private $propertyExpression; @@ -299,7 +295,7 @@ public function setPropertyWithCompoundValidationRule(int $propertyWithCompoundV $this->propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; } - #[Assert\Count(min: "0", max: "10")] + #[Assert\Count(min: '0', max: '10')] public function setPropertyNotBlank(int $propertyNotBlank): void { $this->propertyNotBlank = $propertyNotBlank; diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php index cf83b6cb3..e5afcfbfa 100644 --- a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php @@ -25,7 +25,9 @@ class SymfonyConstraintsWithValidationGroups * @var int * * @Groups("test") + * * @Assert\NotBlank(groups={"test"}) + * * @Assert\Range(min=1, max=100) */ public $property; @@ -41,6 +43,7 @@ class SymfonyConstraintsWithValidationGroups * @var array * * @OA\Property(type="array", @OA\Items(type="string")) + * * @Assert\Valid */ public $propertyArray; @@ -52,8 +55,8 @@ class SymfonyConstraintsWithValidationGroups * @var int */ #[Assert\Range(min: 1, max: 100)] - #[Assert\NotBlank(groups: ["test"])] - #[Groups("test")] + #[Assert\NotBlank(groups: ['test'])] + #[Groups('test')] public $property; /** diff --git a/Tests/Functional/Entity/User.php b/Tests/Functional/Entity/User.php index c9e9b42dc..0e4edec48 100644 --- a/Tests/Functional/Entity/User.php +++ b/Tests/Functional/Entity/User.php @@ -63,12 +63,14 @@ class User /** * @var float + * * @OA\Property(default = 0.0) */ private $money; /** * @var \DateTime + * * @OA\Property(property="creationDate") */ private $createdAt; @@ -309,4 +311,4 @@ public function setDateAsInterface(\DateTimeInterface $dateAsInterface) $this->dateAsInterface = $dateAsInterface; } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/VirtualProperty.php b/Tests/Functional/Entity/VirtualProperty.php index 52ab283ef..0f5dfe604 100644 --- a/Tests/Functional/Entity/VirtualProperty.php +++ b/Tests/Functional/Entity/VirtualProperty.php @@ -17,6 +17,7 @@ * Class VirtualProperty. * * @Serializer\ExclusionPolicy("all") + * * @Serializer\VirtualProperty( * "email", * exp="object.user.email", @@ -27,7 +28,9 @@ class VirtualProperty { /** * @var int + * * @Serializer\Type("integer") + * * @Serializer\Expose */ private $id; @@ -39,7 +42,9 @@ class VirtualProperty /** * @Serializer\Accessor(getter="getFoo", setter="setFoo") + * * @Serializer\Type("string") + * * @Serializer\Expose * * Ensures https://github.com/nelmio/NelmioApiDocBundle/issues/1708 is fixed. diff --git a/Tests/Functional/EntityExcluded/ApiPlatform2/Dummy.php b/Tests/Functional/EntityExcluded/ApiPlatform2/Dummy.php index 5b9ce094f..b8c9e6a27 100644 --- a/Tests/Functional/EntityExcluded/ApiPlatform2/Dummy.php +++ b/Tests/Functional/EntityExcluded/ApiPlatform2/Dummy.php @@ -38,6 +38,7 @@ class Dummy * @var string * * @Assert\NotBlank + * * @ApiProperty(iri="http://schema.org/name") */ private $name; diff --git a/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php b/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php index 6cf7d4f16..7046b2969 100644 --- a/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php +++ b/Tests/Functional/EntityExcluded/Symfony7/SerializedNameEntity.php @@ -21,13 +21,13 @@ class SerializedNameEntity /** * @var string */ - #[SerializedName("notfoo")] + #[SerializedName('notfoo')] public $foo; /** * Tests serialized name feature. */ - #[SerializedName("notwhatyouthink")] + #[SerializedName('notwhatyouthink')] public function setBar(string $bar) { } diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 237f0790c..222dce79e 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -37,12 +37,11 @@ class TestKernel extends Kernel { - const USE_JMS = 1; - const USE_BAZINGA = 2; - const ERROR_ARRAY_ITEMS = 4; - const USE_VALIDATION_GROUPS = 8; - use MicroKernelTrait; + public const USE_JMS = 1; + public const USE_BAZINGA = 2; + public const ERROR_ARRAY_ITEMS = 4; + public const USE_VALIDATION_GROUPS = 8; private $flags; @@ -55,9 +54,6 @@ public function __construct(int $flags = 0) $this->flags = $flags; } - /** - * {@inheritdoc} - */ public function registerBundles(): iterable { $bundles = [ @@ -84,9 +80,6 @@ public function registerBundles(): iterable return $bundles; } - /** - * {@inheritdoc} - */ protected function configureRoutes($routes) { if (self::MAJOR_VERSION < 7) { @@ -132,9 +125,6 @@ private function import($routes, $resource, $prefix, $type) } } - /** - * {@inheritdoc} - */ protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) { $framework = [ @@ -166,7 +156,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'strict_variables' => '%kernel.debug%', 'exception_controller' => null, ]); - + if (self::MAJOR_VERSION < 7) { $c->loadFromExtension('sensio_framework_extra', [ 'router' => [ @@ -175,7 +165,6 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ]); } - $c->loadFromExtension('api_platform', [ 'mapping' => ['paths' => [ !class_exists(ApiProperty::class) @@ -338,17 +327,11 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load $c->setDefinition('nelmio.test.jms.virtual_type.describer', $def); } - /** - * {@inheritdoc} - */ public function getCacheDir(): string { return parent::getCacheDir().'/'.$this->flags; } - /** - * {@inheritdoc} - */ public function getLogDir(): string { return parent::getLogDir().'/'.$this->flags; diff --git a/Tests/Functional/WebTestCase.php b/Tests/Functional/WebTestCase.php index 846c59a42..83f58bc91 100644 --- a/Tests/Functional/WebTestCase.php +++ b/Tests/Functional/WebTestCase.php @@ -14,7 +14,6 @@ use OpenApi\Annotations as OA; use OpenApi\Generator; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\KernelInterface; class WebTestCase extends BaseWebTestCase diff --git a/Tests/Model/ModelRegistryTest.php b/Tests/Model/ModelRegistryTest.php index 2b36455cf..59f559d7b 100644 --- a/Tests/Model/ModelRegistryTest.php +++ b/Tests/Model/ModelRegistryTest.php @@ -151,8 +151,6 @@ public function testNameCollisionsAreLoggedWithAlternativeNames() /** * @dataProvider getNameAlternatives - * - * @param $expected */ public function testNameAliasingForObjects(string $expected, $groups, array $alternativeNames) { diff --git a/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php index e9b42fe45..4aedd3798 100644 --- a/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php @@ -27,6 +27,7 @@ class AnnotationReaderTest extends TestCase /** * @param object $entity + * * @dataProvider provideProperty */ public function testProperty($entity) diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index 4e155cd76..55026e6ce 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -41,6 +41,7 @@ public function testUpdatePropertyFix1283() $entity = new class() { /** * @Assert\NotBlank() + * * @Assert\Length(min = 1) */ private $property1; @@ -66,6 +67,7 @@ public function testUpdatePropertyFix1283() /** * @param object $entity + * * @dataProvider provideOptionalProperty */ public function testOptionalProperty($entity) @@ -93,6 +95,7 @@ public function provideOptionalProperty(): iterable yield 'Annotations' => [new class() { /** * @Assert\NotBlank(allowNull = true) + * * @Assert\Length(min = 1) */ private $property1; @@ -115,6 +118,7 @@ public function provideOptionalProperty(): iterable /** * @param object $entity + * * @dataProvider provideAssertChoiceResultsInNumericArray */ public function testAssertChoiceResultsInNumericArray($entity) @@ -141,6 +145,7 @@ public function provideAssertChoiceResultsInNumericArray(): iterable yield 'Annotations' => [new class() { /** * @Assert\Length(min = 1) + * * @Assert\Choice(choices=TEST_ASSERT_CHOICE_STATUSES) */ private $property1; @@ -157,6 +162,7 @@ public function provideAssertChoiceResultsInNumericArray(): iterable /** * @param object $entity + * * @dataProvider provideMultipleChoiceConstraintsApplyEnumToItems */ public function testMultipleChoiceConstraintsApplyEnumToItems($entity) @@ -192,7 +198,9 @@ public function provideMultipleChoiceConstraintsApplyEnumToItems(): iterable /** * @param object $entity + * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1780 + * * @dataProvider provideLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet */ public function testLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet($entity) @@ -228,7 +236,9 @@ public function provideLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet(): itera /** * @param object $entity + * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1780 + * * @dataProvider provideLengthConstraintDoesNotSetMinLengthIfMinIsNotSet */ public function testLengthConstraintDoesNotSetMinLengthIfMinIsNotSet($entity) @@ -297,7 +307,9 @@ public function testCompoundValidationRules() /** * @param object $entity + * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1821 + * * @dataProvider provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet */ public function testCountConstraintDoesNotSetMinItemsIfMinIsNotSet($entity) @@ -333,7 +345,9 @@ public function provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet(): iterabl /** * @param object $entity + * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1821 + * * @dataProvider provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet */ public function testCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet($entity) @@ -369,7 +383,9 @@ public function provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet(): iterabl /** * @param object $entity + * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1822 + * * @dataProvider provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet */ public function testRangeConstraintDoesNotSetMaximumIfMaxIsNotSet($entity) @@ -405,7 +421,9 @@ public function provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet(): iterable /** * @param object $entity + * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1822 + * * @dataProvider provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet */ public function testRangeConstraintDoesNotSetMinimumIfMinIsNotSet($entity) @@ -444,6 +462,7 @@ public function provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet(): iterable * group when `group={"someGroup"}` is not set. * * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1857 + * * @dataProvider provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet */ public function testReaderWithValidationGroupsEnabledChecksForDefaultGroupWhenNoSerializationGroupsArePassed($entity) @@ -464,6 +483,7 @@ public function testReaderWithValidationGroupsEnabledChecksForDefaultGroupWhenNo /** * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1857 + * * @dataProvider provideConstraintsWithGroups */ public function testReaderWithValidationGroupsEnabledDoesNotReadAnnotationsWithoutDefaultGroupIfNoGroupsArePassed($entity) @@ -487,6 +507,7 @@ public function testReaderWithValidationGroupsEnabledDoesNotReadAnnotationsWitho /** * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1857 + * * @dataProvider provideConstraintsWithGroups */ public function testReaderWithValidationGroupsEnabledReadsOnlyConstraintsWithGroupsProvided($entity) @@ -511,6 +532,7 @@ public function testReaderWithValidationGroupsEnabledReadsOnlyConstraintsWithGro /** * @group https://github.com/nelmio/NelmioApiDocBundle/issues/1857 + * * @dataProvider provideConstraintsWithGroups */ public function testReaderWithValidationGroupsEnabledCanReadFromMultipleValidationGroups($entity) @@ -538,6 +560,7 @@ public function provideConstraintsWithGroups(): iterable yield 'Annotations' => [new class() { /** * @Assert\NotBlank() + * * @Assert\Range(min=1, groups={"other"}) */ private $property1; diff --git a/Tests/ModelDescriber/ApplyOpenApiDiscriminatorTraitTest.php b/Tests/ModelDescriber/ApplyOpenApiDiscriminatorTraitTest.php index 49271dffb..20fb7582b 100644 --- a/Tests/ModelDescriber/ApplyOpenApiDiscriminatorTraitTest.php +++ b/Tests/ModelDescriber/ApplyOpenApiDiscriminatorTraitTest.php @@ -24,8 +24,8 @@ class ApplyOpenApiDiscriminatorTraitTest extends TestCase { use ApplyOpenApiDiscriminatorTrait; - const GROUPS = ['test']; - const OPTIONS = ['test' => 123]; + public const GROUPS = ['test']; + public const OPTIONS = ['test' => 123]; private $schema; diff --git a/Tests/Render/RenderOpenApiTest.php b/Tests/Render/RenderOpenApiTest.php index 514b0c822..c8d6cc164 100644 --- a/Tests/Render/RenderOpenApiTest.php +++ b/Tests/Render/RenderOpenApiTest.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Render; -use InvalidArgumentException; use Nelmio\ApiDocBundle\Render\OpenApiRenderer; use Nelmio\ApiDocBundle\Render\RenderOpenApi; use OpenApi\Annotations\OpenApi; @@ -35,14 +34,14 @@ public function testRender() public function testUnknownFormat() { $availableOpenApiRenderers = []; - $this->expectExceptionObject(new InvalidArgumentException(sprintf('Format "%s" is not supported.', $this->format))); + $this->expectExceptionObject(new \InvalidArgumentException(sprintf('Format "%s" is not supported.', $this->format))); $this->renderOpenApi(...$availableOpenApiRenderers); } public function testUnknownArea() { $this->hasArea = false; - $this->expectExceptionObject(new InvalidArgumentException(sprintf('Area "%s" is not supported.', $this->area))); + $this->expectExceptionObject(new \InvalidArgumentException(sprintf('Area "%s" is not supported.', $this->area))); $this->renderOpenApi(); } diff --git a/Tests/Routing/FilteredRouteCollectionBuilderTest.php b/Tests/Routing/FilteredRouteCollectionBuilderTest.php index 32cc91a98..d4f63b593 100644 --- a/Tests/Routing/FilteredRouteCollectionBuilderTest.php +++ b/Tests/Routing/FilteredRouteCollectionBuilderTest.php @@ -72,6 +72,7 @@ public function testFilter() /** * @group legacy + * * @expectedDeprecation Passing an indexed array with a collection of path patterns as argument 1 for `Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder::__construct()` is deprecated since 3.2.0, expected structure is an array containing parameterized options. */ public function testFilterWithDeprecatedArgument() @@ -186,6 +187,7 @@ public function getMatchingRoutes(): iterable /** * @group test + * * @dataProvider getMatchingRoutesWithAnnotation */ public function testMatchingRoutesWithAnnotation(string $name, Route $route, array $options = []) diff --git a/Tests/Util/ControllerReflectorTest.php b/Tests/Util/ControllerReflectorTest.php index d44b0dbde..50a6408ff 100644 --- a/Tests/Util/ControllerReflectorTest.php +++ b/Tests/Util/ControllerReflectorTest.php @@ -5,7 +5,6 @@ use Nelmio\ApiDocBundle\Tests\Functional\Controller\BazingaController; use Nelmio\ApiDocBundle\Util\ControllerReflector; use PHPUnit\Framework\TestCase; -use ReflectionMethod; use Symfony\Component\DependencyInjection\Container; class ControllerReflectorTest extends TestCase @@ -14,11 +13,11 @@ public function testGetReflectionMethod(): void { $controllerReflector = new ControllerReflector(new Container()); $this->assertEquals( - ReflectionMethod::class, + \ReflectionMethod::class, get_class($controllerReflector->getReflectionMethod([BazingaController::class, 'userAction'])) ); $this->assertEquals( - ReflectionMethod::class, + \ReflectionMethod::class, get_class($controllerReflector->getReflectionMethod(BazingaController::class.'::userAction')) ); $this->assertNull( From c97bd00941f95cadad1000700c408664b0804047 Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Mon, 11 Dec 2023 12:21:09 +0100 Subject: [PATCH 03/54] fix: adds missing use statement - somehow rebase deletes it again :( --- Tests/Functional/WebTestCase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Functional/WebTestCase.php b/Tests/Functional/WebTestCase.php index 83f58bc91..846c59a42 100644 --- a/Tests/Functional/WebTestCase.php +++ b/Tests/Functional/WebTestCase.php @@ -14,6 +14,7 @@ use OpenApi\Annotations as OA; use OpenApi\Generator; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\KernelInterface; class WebTestCase extends BaseWebTestCase From 4207f884d5a53e9b156e3fad080344a65e4cf229 Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Mon, 11 Dec 2023 16:15:29 +0100 Subject: [PATCH 04/54] fix: fixes ci --- .github/workflows/continuous-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 514297e40..9cc3fe809 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -62,7 +62,7 @@ jobs: restore-keys: ${{ runner.os }}-composer- - name: Remove packages not compatible symfony 7 - if: matrix.symfony-require == '7.0' + if: matrix.symfony-require == '7.0.*' run: | composer remove friendsofsymfony/rest-bundle sensio/framework-extra-bundle jms/serializer-bundle willdurand/hateoas-bundle --no-update --dev From 4988cfeb4030836e26bc4edc91f2a87d865a4265 Mon Sep 17 00:00:00 2001 From: Faizan Akram Date: Mon, 11 Dec 2023 16:51:53 +0100 Subject: [PATCH 05/54] fix: fixes all failing unit tests - addresses feedback from review (import OpenApi\Attribtues as OAT) --- .../Controller/ClassApiController.php | 4 +- .../Controller/InvokableController.php | 4 +- .../Controller/SerializedNameController.php | 4 +- .../Functional/Controller/TestController.php | 4 +- .../Entity/EntityWithAlternateType.php | 5 +- .../Entity/EntityWithNullableSchemaSet.php | 14 +- .../Entity/EntityWithObjectType.php | 4 +- Tests/Functional/Entity/EntityWithRef.php | 4 +- ...SymfonyConstraintsWithValidationGroups.php | 5 +- Tests/Functional/Entity/User.php | 20 +- Tests/Functional/WebTestCase.php | 15 +- .../SymfonyConstraintAnnotationReaderTest.php | 240 +++++++++++------- 12 files changed, 191 insertions(+), 132 deletions(-) diff --git a/Tests/Functional/Controller/ClassApiController.php b/Tests/Functional/Controller/ClassApiController.php index f2dc75184..b85e731b2 100644 --- a/Tests/Functional/Controller/ClassApiController.php +++ b/Tests/Functional/Controller/ClassApiController.php @@ -13,7 +13,7 @@ use Nelmio\ApiDocBundle\Annotation\Security; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Response; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; @@ -39,7 +39,7 @@ public function securityAction() #[Route('/api', host: 'api.example.com')] class ClassApiController { - #[Response(response: 201, description: '')] + #[OAT\Response(response: 201, description: '')] #[Route('/security/class')] public function securityAction() { diff --git a/Tests/Functional/Controller/InvokableController.php b/Tests/Functional/Controller/InvokableController.php index d91013a16..7cecdd472 100644 --- a/Tests/Functional/Controller/InvokableController.php +++ b/Tests/Functional/Controller/InvokableController.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Response; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; @@ -37,7 +37,7 @@ public function __invoke() /** * Prevents a regression (see https://github.com/nelmio/NelmioApiDocBundle/issues/1559). */ - #[Response(response: 200, description: 'Invokable!')] + #[OAT\Response(response: 200, description: 'Invokable!')] #[Route('/api/invoke', host: 'api.example.com', name: 'invokable', methods: ['GET'])] class InvokableController { diff --git a/Tests/Functional/Controller/SerializedNameController.php b/Tests/Functional/Controller/SerializedNameController.php index 47cf8389a..1f27bd75e 100644 --- a/Tests/Functional/Controller/SerializedNameController.php +++ b/Tests/Functional/Controller/SerializedNameController.php @@ -15,7 +15,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\SerializedNameEnt; use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\Symfony7\SerializedNameEntity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Response; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; @@ -48,7 +48,7 @@ public function serializedNameAction() #[Route('/api', host: 'api.example.com')] class SerializedNameController { - #[Response(response: 200, description: 'success', attachables: [new Model(type: SerializedNameEntity::class)])] + #[OAT\Response(response: 200, description: 'success', attachables: [new Model(type: SerializedNameEntity::class)])] #[Route('/serializename', methods: ['GET'])] public function serializedNameAction() { diff --git a/Tests/Functional/Controller/TestController.php b/Tests/Functional/Controller/TestController.php index 77f33d288..0328086d7 100644 --- a/Tests/Functional/Controller/TestController.php +++ b/Tests/Functional/Controller/TestController.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Response; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; @@ -38,7 +38,7 @@ public function testAction() #[Route('/test', host: 'api-test.example.com')] class TestController { - #[Response(response: 200, description: 'Test')] + #[OAT\Response(response: 200, description: 'Test')] #[Route('/test/', methods: ['GET'])] public function testAction() { diff --git a/Tests/Functional/Entity/EntityWithAlternateType.php b/Tests/Functional/Entity/EntityWithAlternateType.php index eaf1aa20d..1c49ffe5c 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType.php +++ b/Tests/Functional/Entity/EntityWithAlternateType.php @@ -12,8 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Items; -use OpenApi\Attributes\Schema; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; if (Kernel::MAJOR_VERSION < 7) { @@ -36,7 +35,7 @@ public function getIterator(): \ArrayIterator } } } else { - #[Schema(type: 'array', items: new Items(type: 'string'))] + #[OAT\Schema(type: 'array', items: new OAT\Items(type: 'string'))] class EntityWithAlternateType implements \IteratorAggregate { /** diff --git a/Tests/Functional/Entity/EntityWithNullableSchemaSet.php b/Tests/Functional/Entity/EntityWithNullableSchemaSet.php index 216800936..6e8d64a89 100644 --- a/Tests/Functional/Entity/EntityWithNullableSchemaSet.php +++ b/Tests/Functional/Entity/EntityWithNullableSchemaSet.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Property; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; if (Kernel::MAJOR_VERSION < 7) { @@ -66,37 +66,37 @@ class EntityWithNullableSchemaSet /** * @var ?string */ - #[Property] + #[OAT\Property] public $nullablePropertyNullableNotSet; /** * @var ?string */ - #[Property(nullable: false)] + #[OAT\Property(nullable: false)] public $nullablePropertyNullableFalseSet; /** * @var ?string */ - #[Property(nullable: true)] + #[OAT\Property(nullable: true)] public $nullablePropertyNullableTrueSet; /** * @var string */ - #[Property] + #[OAT\Property] public $nonNullablePropertyNullableNotSet; /** * @var string */ - #[Property(nullable: false)] + #[OAT\Property(nullable: false)] public $nonNullablePropertyNullableFalseSet; /** * @var string */ - #[Property(nullable: true)] + #[OAT\Property(nullable: true)] public $nonNullablePropertyNullableTrueSet; } } diff --git a/Tests/Functional/Entity/EntityWithObjectType.php b/Tests/Functional/Entity/EntityWithObjectType.php index 00235ab77..10b8b2fee 100644 --- a/Tests/Functional/Entity/EntityWithObjectType.php +++ b/Tests/Functional/Entity/EntityWithObjectType.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Schema; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; if (Kernel::MAJOR_VERSION < 7) { @@ -27,7 +27,7 @@ class EntityWithObjectType public $notIgnored = 'this should be read'; } } else { - #[Schema(type: 'object')] + #[OAT\Schema(type: 'object')] class EntityWithObjectType { /** diff --git a/Tests/Functional/Entity/EntityWithRef.php b/Tests/Functional/Entity/EntityWithRef.php index ca48276c2..6b04fa592 100644 --- a/Tests/Functional/Entity/EntityWithRef.php +++ b/Tests/Functional/Entity/EntityWithRef.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Schema; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; if (Kernel::MAJOR_VERSION < 7) { @@ -27,7 +27,7 @@ class EntityWithRef public $ignored = 'this property should be ignored because of the annotation above'; } } else { - #[Schema(ref: '#/components/schemas/Test')] + #[OAT\Schema(ref: '#/components/schemas/Test')] class EntityWithRef { /** diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php index e5afcfbfa..f0131e119 100644 --- a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php @@ -12,8 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Items; -use OpenApi\Attributes\Property; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -68,7 +67,7 @@ class SymfonyConstraintsWithValidationGroups /** * @var array */ - #[Property(type: 'array', items: new Items(type: 'string'))] + #[OAT\Property(type: 'array', items: new OAT\Items(type: 'string'))] #[Assert\Valid] public $propertyArray; } diff --git a/Tests/Functional/Entity/User.php b/Tests/Functional/Entity/User.php index 0e4edec48..b94af92a9 100644 --- a/Tests/Functional/Entity/User.php +++ b/Tests/Functional/Entity/User.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Property; +use OpenApi\Attributes as OAT; use Symfony\Component\HttpKernel\Kernel; if (Kernel::MAJOR_VERSION < 7) { @@ -180,10 +180,10 @@ class User /** * @var int */ - #[Property(description: 'User id', readOnly: true, title: 'userid', default: null)] + #[OAT\Property(description: 'User id', readOnly: true, title: 'userid', default: null)] private $id; - #[Property(type: 'string', readOnly: false)] + #[OAT\Property(type: 'string', readOnly: false)] private $email; /** @@ -191,31 +191,31 @@ class User * * @var string[] */ - #[Property(description: 'User roles', title: 'roles', example: ['ADMIN', 'SUPERUSER'], default: ['USER'])] + #[OAT\Property(description: 'User roles', title: 'roles', example: ['ADMIN', 'SUPERUSER'], default: ['USER'])] private $roles; /** * User Location. */ - #[Property(type: 'string')] + #[OAT\Property(type: 'string')] private $location; /** * @var int */ - #[Property(type: 'string')] + #[OAT\Property(type: 'string')] private $friendsNumber; /** * @var float */ - #[Property(default: 0.0)] + #[OAT\Property(default: 0.0)] private $money; /** * @var \DateTime */ - #[Property(property: 'creationDate')] + #[OAT\Property(property: 'creationDate')] private $createdAt; /** @@ -236,7 +236,7 @@ class User /** * @var string */ - #[Property(enum: ['disabled', 'enabled'])] + #[OAT\Property(enum: ['disabled', 'enabled'])] private $status; /** @@ -249,7 +249,7 @@ public function setMoney(float $money) $this->money = $money; } - #[Property(example: 1)] + #[OAT\Property(example: 1)] public function setId(int $id) { $this->id = $id; diff --git a/Tests/Functional/WebTestCase.php b/Tests/Functional/WebTestCase.php index 846c59a42..51b9b7951 100644 --- a/Tests/Functional/WebTestCase.php +++ b/Tests/Functional/WebTestCase.php @@ -171,14 +171,19 @@ public function assertNotHasProperty($property, OA\AbstractAnnotation $annotatio } /** - * BC symfony < 5.3. + * BC symfony < 5.3 and symfony >= 7 + * + * KernelTestCase::getContainer has a Container return type object in symfony 7 + * which is incompatible with the return type of previous versions or + * at least the return type of overridden method (which was added for BC compatibility), + * hence moving it to the magic method. */ - protected static function getContainer(): ContainerInterface + public static function __callStatic(string $name, array $arguments) { - if (method_exists(parent::class, 'getContainer')) { - return parent::getContainer(); + if ('getContainer' === $name) { + return static::$container; } - return static::$container; + return null; } } diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index 55026e6ce..f1766bad2 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -12,15 +12,15 @@ namespace Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations; use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Annotations\Reader; use Nelmio\ApiDocBundle\ModelDescriber\Annotations\SymfonyConstraintAnnotationReader; use Nelmio\ApiDocBundle\Tests\Helper; use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert; use OpenApi\Annotations as OA; -use OpenApi\Attributes\Property; -use OpenApi\Attributes\Schema; use OpenApi\Context; use OpenApi\Generator; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints as Assert; @@ -38,18 +38,30 @@ protected function setUp(): void public function testUpdatePropertyFix1283() { - $entity = new class() { - /** - * @Assert\NotBlank() - * - * @Assert\Length(min = 1) - */ - private $property1; - /** - * @Assert\NotBlank() - */ - private $property2; - }; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + $entity = new class() { + /** + * @Assert\NotBlank() + * + * @Assert\Length(min = 1) + */ + private $property1; + + /** + * @Assert\NotBlank() + */ + private $property2; + }; + } else { + $entity = new class() { + #[Assert\Length(min: 1)] + #[Assert\NotBlank()] + private $property1; + + #[Assert\NotBlank()] + private $property2; + }; + } $schema = $this->createObj(OA\Schema::class, []); $schema->merge([$this->createObj(OA\Property::class, ['property' => 'property1'])]); @@ -92,18 +104,23 @@ public function testOptionalProperty($entity) public function provideOptionalProperty(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\NotBlank(allowNull = true) - * - * @Assert\Length(min = 1) - */ - private $property1; - /** - * @Assert\NotBlank() - */ - private $property2; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\NotBlank(allowNull = true) + * + * @Assert\Length(min = 1) + */ + private $property1; + + /** + * @Assert\NotBlank() + */ + private $property2; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -142,14 +159,18 @@ public function provideAssertChoiceResultsInNumericArray(): iterable 2 => 'blocked', ]); - yield 'Annotations' => [new class() { - /** - * @Assert\Length(min = 1) - * - * @Assert\Choice(choices=TEST_ASSERT_CHOICE_STATUSES) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Length(min = 1) + * + * @Assert\Choice(choices=TEST_ASSERT_CHOICE_STATUSES) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -181,12 +202,14 @@ public function testMultipleChoiceConstraintsApplyEnumToItems($entity) public function provideMultipleChoiceConstraintsApplyEnumToItems(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Choice(choices={"one", "two"}, multiple=true) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [new class() { + /** + * @Assert\Choice(choices={"one", "two"}, multiple=true) + */ + private $property1; + }]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -219,12 +242,16 @@ public function testLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet($entity) public function provideLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Length(min = 1) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Length(min = 1) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -257,12 +284,16 @@ public function testLengthConstraintDoesNotSetMinLengthIfMinIsNotSet($entity) public function provideLengthConstraintDoesNotSetMinLengthIfMinIsNotSet(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Length(max = 100) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Length(max = 100) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -274,12 +305,19 @@ public function provideLengthConstraintDoesNotSetMinLengthIfMinIsNotSet(): itera public function testCompoundValidationRules() { - $entity = new class() { - /** - * @CustomAssert\CompoundValidationRule() - */ - private $property1; - }; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + $entity = new class() { + /** + * @CustomAssert\CompoundValidationRule() + */ + private $property1; + }; + } else { + $entity = new class() { + #[CustomAssert\CompoundValidationRule()] + private $property1; + }; + } $propertyName = 'property1'; $schema = $this->createObj(OA\Schema::class, []); @@ -328,12 +366,16 @@ public function testCountConstraintDoesNotSetMinItemsIfMinIsNotSet($entity) public function provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Count(max = 10) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Count(max = 10) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -366,12 +408,16 @@ public function testCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet($entity) public function provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Count(min = 10) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Count(min = 10) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -404,12 +450,16 @@ public function testRangeConstraintDoesNotSetMaximumIfMaxIsNotSet($entity) public function provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Range(min = 10) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Range(min = 10) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -442,12 +492,16 @@ public function testRangeConstraintDoesNotSetMinimumIfMinIsNotSet($entity) public function provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\Range(max = 10) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [ + new class() { + /** + * @Assert\Range(max = 10) + */ + private $property1; + } + ]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { @@ -512,9 +566,9 @@ public function testReaderWithValidationGroupsEnabledDoesNotReadAnnotationsWitho */ public function testReaderWithValidationGroupsEnabledReadsOnlyConstraintsWithGroupsProvided($entity) { - $schema = $this->createObj(Schema::class, []); + $schema = $this->createObj(OA\Schema::class, []); $schema->merge([ - $this->createObj(Property::class, ['property' => 'property1']), + $this->createObj(OA\Property::class, ['property' => 'property1']), ]); $reader = $this->createConstraintReaderWithValidationGroupsEnabled(); $reader->setSchema($schema); @@ -557,14 +611,16 @@ public function testReaderWithValidationGroupsEnabledCanReadFromMultipleValidati public function provideConstraintsWithGroups(): iterable { - yield 'Annotations' => [new class() { - /** - * @Assert\NotBlank() - * - * @Assert\Range(min=1, groups={"other"}) - */ - private $property1; - }]; + if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + yield 'Annotations' => [new class() { + /** + * @Assert\NotBlank() + * + * @Assert\Range(min=1, groups={"other"}) + */ + private $property1; + }]; + } if (\PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { From ebfff92c18761788aa59256ff44543ef82732dba Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:48:27 +0100 Subject: [PATCH 06/54] Add symfony/expression-language to dev --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index f6425bd12..3c38154ec 100644 --- a/composer.json +++ b/composer.json @@ -46,6 +46,7 @@ "symfony/templating": "^5.4|^6.0|^7.0", "symfony/twig-bundle": "^5.4|^6.0|^7.0", "symfony/validator": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", "api-platform/core": "^2.7.0|^3", "symfony/deprecation-contracts": "^2.1|^3", From d88b9e5556d14ffc0fef4aa62d3307843d6697a0 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:51:34 +0100 Subject: [PATCH 07/54] Remove kernel version check --- Tests/Functional/Controller/ApiController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index 798d2a286..9b1e87f9a 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -11,10 +11,9 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -if (Kernel::MAJOR_VERSION >= 7) { +if (PHP_VERSION_ID >= 80100) { #[Route('/api', name: 'api_', host: 'api.example.com')] class ApiController extends ApiController81 { From f9cbd31d2a9d5be7cb43b62cbb4ef457ffdd34f6 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:52:12 +0100 Subject: [PATCH 08/54] No longer extend ApiController80 --- .../Functional/Controller/ApiController81.php | 358 +++++++++++++++++- 1 file changed, 357 insertions(+), 1 deletion(-) diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index 69d8ed490..3e4f36e2a 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -18,9 +18,365 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; +use Nelmio\ApiDocBundle\Annotation\Operation; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArticleInterface; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\CompoundEntity; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithNullableSchemaSet; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithObjectType; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; +use Nelmio\ApiDocBundle\Tests\Functional\Form\DummyType; +use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithAlternateSchemaType; +use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithModel; +use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithRefType; +use Nelmio\ApiDocBundle\Tests\Functional\Form\UserType; -class ApiController81 extends ApiController80 +class ApiController81 { + #[OA\Get( + responses: [ + new OA\Response( + response: '200', + description: 'Success', + attachables: [ + new Model(type: Article::class, groups: ['light']), + ], + ) + ], + )] + #[OA\Parameter(ref: '#/components/parameters/test')] + #[Route('/article/{id}', methods: ['GET'])] + #[OA\Parameter(name: 'Accept-Version', in: 'header', schema: new OA\Schema(type: 'string'))] + #[OA\Parameter(name: 'Application-Name', in: 'header', schema: new OA\Schema(type: 'string'))] + public function fetchArticleAction() + { + } + #[OA\Get( + responses: [ + new OA\Response( + response: '200', + description: 'Success', + attachables: [ + new Model(type: ArticleInterface::class, groups: ['light']), + ], + ) + ], + )] + #[OA\Parameter(ref: '#/components/parameters/test')] + #[Route('/article-interface/{id}', methods: ['GET'])] + #[OA\Parameter(name: 'Accept-Version', in: 'header', schema: new OA\Schema(type: 'string'))] + #[OA\Parameter(name: 'Application-Name', in: 'header', schema: new OA\Schema(type: 'string'))] + public function fetchArticleInterfaceAction() + { + } + + #[Route('/swagger', methods: ['GET', 'LINK'])] + #[Route('/swagger2', methods: ['GET'])] + #[Operation([ + 'responses' => [ + new OA\Response( + response: '201', + description: 'An example resource', + ), + ], + ])] + #[OA\Get( + path: '/api/swagger2', + parameters: [ + new OA\Parameter(name: 'Accept-Version', in: 'header', schema: new OA\Schema(type: 'string')), + ], + )] + #[OA\Post( + path: '/api/swagger2', + responses: [ + new OA\Response( + response: '203', + description: 'but 203 is not actually allowed (wrong method)', + ), + ], + )] + public function swaggerAction() + { + } + + #[Route('/swagger/implicit', methods: ['GET', 'POST'])] + #[OA\Response( + response: '201', + description: 'Operation automatically detected', + attachables: [ + new Model(type: User::class), + ], + )] + #[OA\RequestBody( + description: 'This is a request body', + content: new OA\JsonContent( + type: 'array', + items: new OA\Items(ref: '#/components/schemas/User'), + ), + )] + #[OA\Tag(name: 'implicit')] + public function implicitSwaggerAction() + { + } + + #[Route('/test/users/{user}', methods: ['POST'], schemes: ['https'], requirements: ['user' => '/foo/'])] + #[OA\Response( + response: '201', + description: 'Operation automatically detected', + attachables: [ + new Model(type: User::class), + ], + )] + #[OA\RequestBody( + description: 'This is a request body', + content: new Model(type: UserType::class, options: ['bar' => 'baz']), + )] + public function submitUserTypeAction() + { + } + + #[Route('/test/{user}', methods: ['GET'], schemes: ['https'], requirements: ['user' => '/foo/'])] + #[OA\Response(response: 200, description: 'sucessful')] + public function userAction() + { + } + + /** + * This action is deprecated. + * + * Please do not use this action. + * + * @deprecated + */ + #[Route('/deprecated', methods: ['GET'])] + public function deprecatedAction() + { + } + + /** + * This action is not documented. It is excluded by the config. + */ + #[Route('/admin', methods: ['GET'])] + public function adminAction() + { + } + + #[OA\Get( + path: '/filtered', + responses: [ + new OA\Response(response: '201', description: ''), + ], + )] + public function filteredAction() + { + } + + #[Route('/form', methods: ['POST'])] + #[OA\RequestBody( + description: 'Request content', + content: new Model(type: DummyType::class), + )] + #[OA\Response(response: 201, description: '')] + public function formAction() + { + } + + #[Route('/form-model', methods: ['POST'])] + #[OA\RequestBody( + description: 'Request content', + content: new Model(type: FormWithModel::class), + )] + #[OA\Response(response: 201, description: '')] + public function formWithModelAction() + { + } + + #[Route('/security', methods: ['GET'])] + #[OA\Response(response: 201, description: '')] + #[Security(name: 'api_key')] + #[Security(name: 'basic')] + #[Security(name: 'oauth2', scopes: ['scope_1'])] + public function securityAction() + { + } + + #[Route('/securityOverride')] + #[OA\Response(response: 201, description: '')] + #[Security(name: 'api_key')] + #[Security(name: null)] + public function securityActionOverride() + { + } + + #[Route('/swagger/symfonyConstraints', methods: ['GET'])] + #[OA\Response( + response: '201', + description: 'Used for symfony constraints test', + content: new Model(type: SymfonyConstraints::class), + )] + public function symfonyConstraintsAction() + { + } + + #[OA\Response( + response: '200', + description: 'Success', + ref: '#/components/schemas/Test', + )] + #[OA\Response( + response: '201', + ref: '#/components/responses/201', + )] + #[Route('/configReference', methods: ['GET'])] + public function configReferenceAction() + { + } + + #[Route('/multi-annotations', methods: ['GET', 'POST'])] + #[OA\Get(description: 'This is the get operation')] + #[OA\Post(description: 'This is post')] + #[OA\Response(response: 200, description: 'Worked well!', attachables: [new Model(type: DummyType::class)])] + public function operationsWithOtherAnnotations() + { + } + + #[Route('/areas/new', methods: ['GET', 'POST'])] + #[Areas(['area', 'area2'])] + public function newAreaAction() + { + } + + #[Route('/compound', methods: ['GET', 'POST'])] + #[OA\Response(response: 200, description: 'Worked well!', attachables: [new Model(type: CompoundEntity::class)])] + public function compoundEntityAction() + { + } + + #[Route('/discriminator-mapping', methods: ['GET', 'POST'])] + #[OA\Response(response: 200, description: 'Worked well!', attachables: [new Model(type: SymfonyDiscriminator::class)])] + public function discriminatorMappingAction() + { + } + + #[Route('/discriminator-mapping-configured-with-file', methods: ['GET', 'POST'])] + #[OA\Response(response: 200, description: 'Worked well!', attachables: [new Model(type: SymfonyDiscriminatorFileMapping::class)])] + public function discriminatorMappingConfiguredWithFileAction() + { + } + + #[Route('/named_route-operation-id', name: 'named_route_operation_id', methods: ['GET', 'POST'])] + #[OA\Response(response: 200, description: 'success')] + public function namedRouteOperationIdAction() + { + } + + #[Route('/custom-operation-id', methods: ['GET', 'POST'])] + #[OA\Get(operationId: 'get-custom-operation-id')] + #[OA\Post(operationId: 'post-custom-operation-id')] + #[OA\Response(response: 200, description: 'success')] + public function customOperationIdAction() + { + } + + #[Route('/swagger/symfonyConstraintsWithValidationGroups', methods: ['GET'])] + #[OA\Response( + response: '201', + description: 'Used for symfony constraints with validation groups test', + content: new Model(type: SymfonyConstraintsWithValidationGroups::class, groups: ['test']), + )] + public function symfonyConstraintsWithGroupsAction() + { + } + + #[Route('/alternate-entity-type', methods: ['GET', 'POST'])] + #[OA\Get(operationId: 'alternate-entity-type')] + #[OA\Response( + response: 200, + description: 'success', + content: new OA\JsonContent( + ref: new Model(type: EntityWithAlternateType::class), + ), + )] + public function alternateEntityType() + { + } + + #[Route('/entity-with-ref', methods: ['GET', 'POST'])] + #[OA\Get(operationId: 'entity-with-ref')] + #[OA\Response( + response: 200, + description: 'success', + content: new OA\JsonContent( + ref: new Model(type: EntityWithRef::class), + ), + )] + public function entityWithRef() + { + } + + /** + * @Route("/entity-with-object-type", methods={"GET", "POST"}) + * + * @OA\Get(operationId="entity-with-object-type") + * + * @OA\Response(response=200, description="success", @OA\JsonContent( + * ref=@Model(type=EntityWithObjectType::class), + * )) + */ + #[Route('/entity-with-object-type', methods: ['GET', 'POST'])] + #[OA\Get(operationId: 'entity-with-object-type')] + #[OA\Response( + response: 200, + description: 'success', + content: new OA\JsonContent( + ref: new Model(type: EntityWithObjectType::class), + ), + )] + public function entityWithObjectType() + { + } + + #[Route('/form-with-alternate-type', methods: ['POST'])] + #[OA\Response( + response: 204, + description: 'Operation automatically detected', + )] + #[OA\RequestBody( + content: new Model(type: FormWithAlternateSchemaType::class), + )] + public function formWithAlternateSchemaType() + { + } + + #[Route('/form-with-ref-type', methods: ['POST'])] + #[OA\Response( + response: 204, + description: 'Operation automatically detected', + )] + #[OA\RequestBody( + content: new Model(type: FormWithRefType::class), + )] + public function formWithRefSchemaType() + { + } + + #[Route('/entity-with-nullable-property-set', methods: ['GET'])] + #[OA\Response( + response: 201, + description: 'Operation automatically detected', + attachables: [ + new Model(type: EntityWithNullableSchemaSet::class), + ], + )] + public function entityWithNullableSchemaSet() + { + } + #[OA\Get(responses: [ new OA\Response( response: '200', From 2ef40b7257a6ebea8674b910a96d82fb39cd3a1d Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:52:32 +0100 Subject: [PATCH 09/54] Fix controller attributes passed to next controller --- Describer/OpenApiPhpDescriber.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Describer/OpenApiPhpDescriber.php b/Describer/OpenApiPhpDescriber.php index 62156a611..d6cc5b791 100644 --- a/Describer/OpenApiPhpDescriber.php +++ b/Describer/OpenApiPhpDescriber.php @@ -69,6 +69,7 @@ public function describe(OA\OpenApi $api) $this->setContext($context); if (!array_key_exists($declaringClass->getName(), $classAnnotations)) { + $classAnnotations = []; if (null !== $this->annotationReader) { $classAnnotations = $this->annotationReader->getClassAnnotations($declaringClass); } From 6f742e74ec5f01ae35c93a79aba3f301bd4a576d Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:52:50 +0100 Subject: [PATCH 10/54] Fix copy mistake --- Tests/Functional/Entity/User.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/Entity/User.php b/Tests/Functional/Entity/User.php index b94af92a9..b06f7f545 100644 --- a/Tests/Functional/Entity/User.php +++ b/Tests/Functional/Entity/User.php @@ -191,7 +191,7 @@ class User * * @var string[] */ - #[OAT\Property(description: 'User roles', title: 'roles', example: ['ADMIN', 'SUPERUSER'], default: ['USER'])] + #[OAT\Property(description: 'User roles', title: 'roles', example: '["ADMIN","SUPERUSER"]', default: ['user'])] private $roles; /** From 13005b7ed8935a03c6c78e50a2a5a3f2f7e82817 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:53:40 +0100 Subject: [PATCH 11/54] Use Route attribute --- Tests/Functional/Controller/FOSRestController.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index 699198d4a..b9a2ed010 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -14,9 +14,7 @@ use Symfony\Component\Routing\Annotation\Route; if (\PHP_VERSION_ID >= 80100) { - /** - * @Route("/api", host="api.example.com") - */ + #[Route("/api", host: "api.example.com")] class FOSRestController extends FOSRestController81 { } From 7a5a8104454e710f7b38dee7a9a855b7464ef489 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:54:30 +0100 Subject: [PATCH 12/54] Fix version skip check --- Tests/Functional/BazingaFunctionalTest.php | 2 +- Tests/Functional/FOSRestTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Functional/BazingaFunctionalTest.php b/Tests/Functional/BazingaFunctionalTest.php index e10514f34..92df0d95a 100644 --- a/Tests/Functional/BazingaFunctionalTest.php +++ b/Tests/Functional/BazingaFunctionalTest.php @@ -19,7 +19,7 @@ class BazingaFunctionalTest extends WebTestCase { protected function setUp(): void { - if (Kernel::MAJOR_VERSION < 7) { + if (Kernel::MAJOR_VERSION >= 7) { $this->markTestSkipped('Not supported in symfony 7'); } diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index 561c21108..0550c9336 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -19,7 +19,7 @@ class FOSRestTest extends WebTestCase { protected function setUp(): void { - if (Kernel::MAJOR_VERSION < 7) { + if (Kernel::MAJOR_VERSION >= 7) { $this->markTestSkipped('Not supported in symfony 7'); } From cd638edad93fba9054f16bca113d148936f81ca0 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:55:19 +0100 Subject: [PATCH 13/54] Skip JMS --- Tests/Functional/JMSFunctionalTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Tests/Functional/JMSFunctionalTest.php b/Tests/Functional/JMSFunctionalTest.php index 9bcc3c3b4..80c91c9c3 100644 --- a/Tests/Functional/JMSFunctionalTest.php +++ b/Tests/Functional/JMSFunctionalTest.php @@ -11,6 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; class JMSFunctionalTest extends WebTestCase @@ -19,6 +20,10 @@ protected function setUp(): void { parent::setUp(); + if (Kernel::MAJOR_VERSION >= 7) { + $this->markTestSkipped('JMS Serializer is not compatible with Symfony 7+'); + } + static::createClient([], ['HTTP_HOST' => 'api.example.com']); } From 7a79bdf862224f03fe6acdd3f1d23d5b904c5804 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:56:17 +0100 Subject: [PATCH 14/54] Implement attribute class variant --- .../Form/FormWithAlternateSchemaType.php | 39 ++++-- Tests/Functional/Form/FormWithRefType.php | 39 ++++-- Tests/Functional/Form/UserType.php | 112 ++++++++++++------ 3 files changed, 132 insertions(+), 58 deletions(-) diff --git a/Tests/Functional/Form/FormWithAlternateSchemaType.php b/Tests/Functional/Form/FormWithAlternateSchemaType.php index 8dc76c853..644468bd2 100644 --- a/Tests/Functional/Form/FormWithAlternateSchemaType.php +++ b/Tests/Functional/Form/FormWithAlternateSchemaType.php @@ -12,20 +12,35 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Form; use OpenApi\Annotations as OA; +use OpenApi\Attributes as OAT; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\InputType; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; -/** - * @OA\Schema(type="string") - */ -class FormWithAlternateSchemaType extends AbstractType -{ - public function buildForm(FormBuilderInterface $builder, array $options): void +if (PHP_VERSION_ID < 80100) { + /** + * @OA\Schema(type="string") + */ + class FormWithAlternateSchemaType extends AbstractType + { + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('ignored', TextType::class, [ + 'required' => false, + ]); + } + } +} else { + #[OAT\Schema(type: 'string')] + class FormWithAlternateSchemaType extends AbstractType { - $builder - ->add('ignored', InputType::class, [ - 'required' => false, - ]); + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('ignored', TextType::class, [ + 'required' => false, + ]); + } } -} +} \ No newline at end of file diff --git a/Tests/Functional/Form/FormWithRefType.php b/Tests/Functional/Form/FormWithRefType.php index 7b8b89c85..7f998e96a 100644 --- a/Tests/Functional/Form/FormWithRefType.php +++ b/Tests/Functional/Form/FormWithRefType.php @@ -12,20 +12,37 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Form; use OpenApi\Annotations as OA; +use OpenApi\Attributes as OAT; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\Extension\Core\Type\InputType; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\HttpKernel\Kernel; -/** - * @OA\Schema(ref="#/components/schemas/Test") - */ -class FormWithRefType extends AbstractType -{ - public function buildForm(FormBuilderInterface $builder, array $options): void +if (PHP_VERSION_ID < 80100) { + /** + * @OA\Schema(ref="#/components/schemas/Test") + */ + class FormWithRefType extends AbstractType + { + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('ignored', TextType::class, [ + 'required' => false, + ]); + } + } +} else { + #[OAT\Schema(ref: '#/components/schemas/Test')] + class FormWithRefType extends AbstractType { - $builder - ->add('ignored', InputType::class, [ - 'required' => false, - ]); + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('ignored', TextType::class, [ + 'required' => false, + ]); + } } } + diff --git a/Tests/Functional/Form/UserType.php b/Tests/Functional/Form/UserType.php index b7155d0f8..717f0379d 100644 --- a/Tests/Functional/Form/UserType.php +++ b/Tests/Functional/Form/UserType.php @@ -13,51 +13,93 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; use OpenApi\Annotations as OA; +use OpenApi\Attributes as OAT; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\OptionsResolver\OptionsResolver; -/** - * @OA\Schema( - * description="this is the description of an user" - * ) - */ -class UserType extends AbstractType -{ - public function buildForm(FormBuilderInterface $builder, array $options): void +if (PHP_VERSION_ID < 80100) { + /** + * @OA\Schema( + * description="this is the description of an user" + * ) + */ + class UserType extends AbstractType { - $builder - ->add('strings', CollectionType::class, [ - 'entry_type' => TextType::class, - 'required' => false, - ]) - ->add('dummy', DummyType::class) - ->add('dummies', CollectionType::class, [ - 'entry_type' => DummyType::class, - ]) - ->add('empty_dummies', CollectionType::class, [ - 'entry_type' => DummyEmptyType::class, - 'required' => false, - ]) - ->add('quz', DummyType::class, ['documentation' => ['type' => 'string', 'description' => 'User type.'], 'required' => false]) - ->add('entity', EntityType::class, ['class' => 'Entity']) - ->add('entities', EntityType::class, ['class' => 'Entity', 'multiple' => true]) - ->add('document', DocumentType::class, ['class' => 'Document']) - ->add('documents', DocumentType::class, ['class' => 'Document', 'multiple' => true]) - ->add('extended_builtin', ExtendedBuiltinType::class, ['required_option' => 'foo']) - ->add('hidden', DummyType::class, ['documentation' => false]) - ->add('save', SubmitType::class); - } + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('strings', CollectionType::class, [ + 'entry_type' => TextType::class, + 'required' => false, + ]) + ->add('dummy', DummyType::class) + ->add('dummies', CollectionType::class, [ + 'entry_type' => DummyType::class, + ]) + ->add('empty_dummies', CollectionType::class, [ + 'entry_type' => DummyEmptyType::class, + 'required' => false, + ]) + ->add('quz', DummyType::class, ['documentation' => ['type' => 'string', 'description' => 'User type.'], 'required' => false]) + ->add('entity', EntityType::class, ['class' => 'Entity']) + ->add('entities', EntityType::class, ['class' => 'Entity', 'multiple' => true]) + ->add('document', DocumentType::class, ['class' => 'Document']) + ->add('documents', DocumentType::class, ['class' => 'Document', 'multiple' => true]) + ->add('extended_builtin', ExtendedBuiltinType::class, ['required_option' => 'foo']) + ->add('hidden', DummyType::class, ['documentation' => false]) + ->add('save', SubmitType::class); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => User::class, + ]); - public function configureOptions(OptionsResolver $resolver): void + $resolver->setRequired('bar'); + } + } +} else { + #[OAT\Schema(description: 'this is the description of an user')] + class UserType extends AbstractType { - $resolver->setDefaults([ - 'data_class' => User::class, - ]); + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('strings', CollectionType::class, [ + 'entry_type' => TextType::class, + 'required' => false, + ]) + ->add('dummy', DummyType::class) + ->add('dummies', CollectionType::class, [ + 'entry_type' => DummyType::class, + ]) + ->add('empty_dummies', CollectionType::class, [ + 'entry_type' => DummyEmptyType::class, + 'required' => false, + ]) + ->add('quz', DummyType::class, ['documentation' => ['type' => 'string', 'description' => 'User type.'], 'required' => false]) + ->add('entity', EntityType::class, ['class' => 'Entity']) + ->add('entities', EntityType::class, ['class' => 'Entity', 'multiple' => true]) + ->add('document', DocumentType::class, ['class' => 'Document']) + ->add('documents', DocumentType::class, ['class' => 'Document', 'multiple' => true]) + ->add('extended_builtin', ExtendedBuiltinType::class, ['required_option' => 'foo']) + ->add('hidden', DummyType::class, ['documentation' => false]) + ->add('save', SubmitType::class); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => User::class, + ]); - $resolver->setRequired('bar'); + $resolver->setRequired('bar'); + } } } From 671fb54222f6f81c6bfabb6fd26c3cc0929da9e0 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 00:56:27 +0100 Subject: [PATCH 15/54] Fix attribute to reflect annotation --- Tests/Functional/Controller/SerializedNameController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/Controller/SerializedNameController.php b/Tests/Functional/Controller/SerializedNameController.php index 1f27bd75e..8a93a258f 100644 --- a/Tests/Functional/Controller/SerializedNameController.php +++ b/Tests/Functional/Controller/SerializedNameController.php @@ -48,7 +48,7 @@ public function serializedNameAction() #[Route('/api', host: 'api.example.com')] class SerializedNameController { - #[OAT\Response(response: 200, description: 'success', attachables: [new Model(type: SerializedNameEntity::class)])] + #[OAT\Response(response: 200, description: 'success', content: new Model(type: SerializedNameEntity::class))] #[Route('/serializename', methods: ['GET'])] public function serializedNameAction() { From 8f06b7e541426bc197853c344078b38768fd838e Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 01:05:17 +0100 Subject: [PATCH 16/54] Fix incorrect model name taken --- Tests/Functional/FunctionalTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index 7a3498b66..9f80d0add 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -544,7 +544,12 @@ public function testSerializedNameAction() $this->markTestSkipped('Annotation @SerializedName doesn\'t exist.'); } - $model = $this->getModel('SerializedNameEnt'); + if (Kernel::MAJOR_VERSION >= 7) { + $model = $this->getModel('SerializedNameEntity'); + } else { + $model = $this->getModel('SerializedNameEnt'); + } + $this->assertCount(2, $model->properties); $this->assertNotHasProperty('foo', $model); From 068055d0ebb7afad68a9e5e058e31da4f23c6f60 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 01:05:49 +0100 Subject: [PATCH 17/54] Re-add ArrayItemsErrorController tests --- .../Controller/ArrayItemsErrorController.php | 42 ++++++++++++------- Tests/Functional/TestKernel.php | 8 ++-- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/Tests/Functional/Controller/ArrayItemsErrorController.php b/Tests/Functional/Controller/ArrayItemsErrorController.php index 98da0cff3..29ce11c09 100644 --- a/Tests/Functional/Controller/ArrayItemsErrorController.php +++ b/Tests/Functional/Controller/ArrayItemsErrorController.php @@ -14,24 +14,38 @@ use Nelmio\ApiDocBundle\Annotation\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArrayItemsError\Foo; use OpenApi\Annotations as OA; +use OpenApi\Attributes as OAT; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Annotation\Route; -/** - * @Route(host="api.example.com") - */ -class ArrayItemsErrorController -{ +if (Kernel::MAJOR_VERSION < 7) { /** - * @Route("/api/error", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=Foo::class) - * ) + * @Route(host="api.example.com") */ - public function errorAction() + class ArrayItemsErrorController + { + /** + * @Route("/api/error", methods={"GET"}) + * + * @OA\Response( + * response=200, + * description="Success", + * + * @Model(type=Foo::class) + * ) + */ + public function errorAction() + { + } + } +} else { + #[Route(host: 'api.example.com')] + class ArrayItemsErrorController { + #[Route('/api/error', methods: ['GET'])] + #[OAT\Response(response: 200, description: 'Success', content: new Model(type: Foo::class))] + public function errorAction() + { + } } } diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 222dce79e..979e9c4bb 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -92,6 +92,10 @@ protected function configureRoutes($routes) $this->import($routes, __DIR__.'/Controller/SerializedNameController.php', '/', self::MAJOR_VERSION < 7 ? 'annotation' : 'attribute'); } + if ($this->flags & self::ERROR_ARRAY_ITEMS) { + $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', self::MAJOR_VERSION < 7 ? 'annotation' : 'attribute'); + } + if (self::MAJOR_VERSION < 7) { if ($this->flags & self::USE_JMS) { $this->import($routes, __DIR__.'/Controller/JMSController.php', '/', 'annotation'); @@ -106,10 +110,6 @@ protected function configureRoutes($routes) } catch (\ReflectionException $e) { } } - - if ($this->flags & self::ERROR_ARRAY_ITEMS) { - $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', 'annotation'); - } } } From c835a6a677abfb5b1cbae5901a4ef06368d4f697 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 01:21:23 +0100 Subject: [PATCH 18/54] Replace get with Response --- Tests/Functional/Controller/ApiController81.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index 3e4f36e2a..07aab15d6 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -38,15 +38,11 @@ class ApiController81 { - #[OA\Get( - responses: [ - new OA\Response( - response: '200', - description: 'Success', - attachables: [ - new Model(type: Article::class, groups: ['light']), - ], - ) + #[OA\Response( + response: '200', + description: 'Success', + attachables: [ + new Model(type: Article::class, groups: ['light']), ], )] #[OA\Parameter(ref: '#/components/parameters/test')] From cc340a42aafd56742c04f912fc316c6f9c0cf045 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 12 Dec 2023 01:32:46 +0100 Subject: [PATCH 19/54] remove leftover annotation --- Tests/Functional/Controller/ApiController81.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index 07aab15d6..ce4e17fdb 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -315,15 +315,6 @@ public function entityWithRef() { } - /** - * @Route("/entity-with-object-type", methods={"GET", "POST"}) - * - * @OA\Get(operationId="entity-with-object-type") - * - * @OA\Response(response=200, description="success", @OA\JsonContent( - * ref=@Model(type=EntityWithObjectType::class), - * )) - */ #[Route('/entity-with-object-type', methods: ['GET', 'POST'])] #[OA\Get(operationId: 'entity-with-object-type')] #[OA\Response( From 3a964b3bcc401e4c6ae173889e026a8c92e19924 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Fri, 15 Dec 2023 18:02:23 +0100 Subject: [PATCH 20/54] ci: do not remove symfony 7 compatible packages --- .github/workflows/continuous-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 9cc3fe809..7d21bd2d4 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -64,7 +64,7 @@ jobs: - name: Remove packages not compatible symfony 7 if: matrix.symfony-require == '7.0.*' run: | - composer remove friendsofsymfony/rest-bundle sensio/framework-extra-bundle jms/serializer-bundle willdurand/hateoas-bundle --no-update --dev + composer remove friendsofsymfony/rest-bundle sensio/framework-extra-bundle --no-update --dev - name: "Install dependencies with composer" env: From be6ea22c69c32e6f0232e7fe442d119218900736 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 15:58:18 +0100 Subject: [PATCH 21/54] fix: remove $supportsLegacyAnnotations --- Tests/Functional/TestKernel.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 979e9c4bb..0b1a5a95f 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -45,8 +45,6 @@ class TestKernel extends Kernel private $flags; - private bool $supportsLegacyAnnotations; - public function __construct(int $flags = 0) { parent::__construct('test'.$flags, true); From a3dfbb8c8ba09f459f3271592472ded29a0a92a3 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 15:59:23 +0100 Subject: [PATCH 22/54] fix: add helper method for annotation availability check --- Tests/Functional/Controller/ApiController.php | 13 +++++++------ .../Functional/Controller/FOSRestController.php | 13 +++++++------ Tests/Functional/FunctionalTest.php | 8 ++++---- Tests/Functional/TestKernel.php | 17 +++++++++++++---- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index 9b1e87f9a..c3488723a 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -11,18 +11,19 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; -if (PHP_VERSION_ID >= 80100) { - #[Route('/api', name: 'api_', host: 'api.example.com')] - class ApiController extends ApiController81 - { - } -} else { +if (TestKernel::isAnnotationsAvailable()) { /** * @Route("/api", name="api_", host="api.example.com") */ class ApiController extends ApiController80 { } +} else { + #[Route('/api', name: 'api_', host: 'api.example.com')] + class ApiController extends ApiController81 + { + } } diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index b9a2ed010..fb0401622 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -11,18 +11,19 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; -if (\PHP_VERSION_ID >= 80100) { - #[Route("/api", host: "api.example.com")] - class FOSRestController extends FOSRestController81 - { - } -} else { +if (TestKernel::isAnnotationsAvailable()) { /** * @Route("/api", host="api.example.com") */ class FOSRestController extends FOSRestController80 { } +} else { + #[Route("/api", host: "api.example.com")] + class FOSRestController extends FOSRestController81 + { + } } diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index 9f80d0add..58ebe2c28 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -64,7 +64,7 @@ public function testFetchArticleAction(string $articleRoute) public function provideArticleRoute(): iterable { - if (interface_exists(Reader::class) && Kernel::MAJOR_VERSION < 7) { + if (interface_exists(Reader::class)) { yield 'Annotations' => ['/api/article/{id}']; } @@ -544,10 +544,10 @@ public function testSerializedNameAction() $this->markTestSkipped('Annotation @SerializedName doesn\'t exist.'); } - if (Kernel::MAJOR_VERSION >= 7) { - $model = $this->getModel('SerializedNameEntity'); - } else { + if (TestKernel::isAnnotationsAvailable()) { $model = $this->getModel('SerializedNameEnt'); + } else { + $model = $this->getModel('SerializedNameEntity'); } $this->assertCount(2, $model->properties); diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 0b1a5a95f..6f45dfaa1 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -80,7 +80,7 @@ public function registerBundles(): iterable protected function configureRoutes($routes) { - if (self::MAJOR_VERSION < 7) { + if (self::isAnnotationsAvailable()) { $this->import($routes, __DIR__.'/Resources/routes.yaml', '/', 'yaml'); } else { $this->import($routes, __DIR__.'/Resources/routes-attributes.yaml', '/', 'yaml'); @@ -131,7 +131,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'test' => null, 'validation' => null, 'form' => null, - 'serializer' => self::MAJOR_VERSION < 7 ? ['enable_annotations' => true] : [] + [ + 'serializer' => self::isAnnotationsAvailable() ? ['enable_annotations' => true] : [] + [ 'mapping' => [ 'paths' => [__DIR__.'/Resources/serializer/'], ], @@ -155,7 +155,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'exception_controller' => null, ]); - if (self::MAJOR_VERSION < 7) { + if (self::isAnnotationsAvailable()) { $c->loadFromExtension('sensio_framework_extra', [ 'router' => [ 'annotations' => false, @@ -171,7 +171,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ]], ]); - if (self::MAJOR_VERSION < 7) { + if (self::isAnnotationsAvailable()) { $c->loadFromExtension('fos_rest', [ 'format_listener' => [ 'rules' => [ @@ -344,4 +344,13 @@ public function unserialize($str) { $this->__construct(unserialize($str)); } + + public static function isAnnotationsAvailable(): bool + { + if (Kernel::MAJOR_VERSION < 7) { + return false; + } + + return PHP_VERSION_ID < 80100; + } } From ce9e7aa4060655f37decb286b8cf2152aa5bcf42 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 16:02:11 +0100 Subject: [PATCH 23/54] refactor: move SerializedNameController to ApiController --- .../Functional/Controller/ApiController80.php | 15 +++++ .../Functional/Controller/ApiController81.php | 7 +++ .../Controller/SerializedNameController.php | 57 ------------------- Tests/Functional/TestKernel.php | 5 -- 4 files changed, 22 insertions(+), 62 deletions(-) delete mode 100644 Tests/Functional/Controller/SerializedNameController.php diff --git a/Tests/Functional/Controller/ApiController80.php b/Tests/Functional/Controller/ApiController80.php index 423aff1fd..6f5187dc2 100644 --- a/Tests/Functional/Controller/ApiController80.php +++ b/Tests/Functional/Controller/ApiController80.php @@ -27,6 +27,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; +use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\SerializedNameEnt; use Nelmio\ApiDocBundle\Tests\Functional\Form\DummyType; use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithAlternateSchemaType; use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithModel; @@ -453,4 +454,18 @@ public function formWithRefSchemaType() public function entityWithNullableSchemaSet() { } + + /** + * @OA\Response( + * response="200", + * description="success", + * + * @Model(type=SerializedNameEnt::class) + * ) + * + * @Route("/serializename", methods={"GET"}) + */ + public function serializedNameAction() + { + } } diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index ce4e17fdb..6fbe86092 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -16,6 +16,7 @@ use Nelmio\ApiDocBundle\Annotation\Security; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; +use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\Symfony7\SerializedNameEntity; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; use Nelmio\ApiDocBundle\Annotation\Operation; @@ -415,4 +416,10 @@ public function inlinePathParameters( public function enum() { } + + #[Route('/serializename', methods: ['GET'])] + #[OA\Response(response: 200, description: 'success', content: new Model(type: SerializedNameEntity::class))] + public function serializedNameAction() + { + } } diff --git a/Tests/Functional/Controller/SerializedNameController.php b/Tests/Functional/Controller/SerializedNameController.php deleted file mode 100644 index 8a93a258f..000000000 --- a/Tests/Functional/Controller/SerializedNameController.php +++ /dev/null @@ -1,57 +0,0 @@ -= 4.2). - * - * @Route("/api", host="api.example.com") - */ - class SerializedNameController - { - /** - * @OA\Response( - * response="200", - * description="success", - * - * @Model(type=SerializedNameEnt::class) - * ) - * - * @Route("/serializename", methods={"GET"}) - */ - public function serializedNameAction() - { - } - } -} else { - /** - * This controller is only loaded when SerializedName exists (sf >= 4.2). - */ - #[Route('/api', host: 'api.example.com')] - class SerializedNameController - { - #[OAT\Response(response: 200, description: 'success', content: new Model(type: SerializedNameEntity::class))] - #[Route('/serializename', methods: ['GET'])] - public function serializedNameAction() - { - } - } -} diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 6f45dfaa1..df69567a0 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -33,7 +33,6 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\Component\Serializer\Annotation\SerializedName; class TestKernel extends Kernel { @@ -86,10 +85,6 @@ protected function configureRoutes($routes) $this->import($routes, __DIR__.'/Resources/routes-attributes.yaml', '/', 'yaml'); } - if (class_exists(SerializedName::class)) { - $this->import($routes, __DIR__.'/Controller/SerializedNameController.php', '/', self::MAJOR_VERSION < 7 ? 'annotation' : 'attribute'); - } - if ($this->flags & self::ERROR_ARRAY_ITEMS) { $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', self::MAJOR_VERSION < 7 ? 'annotation' : 'attribute'); } From 0545d0323252761c51d116fe4808b0eeb415cfc7 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 16:03:49 +0100 Subject: [PATCH 24/54] fix: create separate controller instead of extending --- .../Controller/ClassApiController.php | 48 ------------------- .../Controller/ClassApiController80.php | 33 +++++++++++++ .../Controller/ClassApiController81.php | 27 +++++++++++ .../Controller/InvokableController.php | 48 ------------------- .../Controller/InvokableController80.php | 32 +++++++++++++ .../Controller/InvokableController81.php | 27 +++++++++++ .../Resources/routes-attributes.yaml | 4 +- Tests/Functional/Resources/routes.yaml | 4 +- 8 files changed, 123 insertions(+), 100 deletions(-) delete mode 100644 Tests/Functional/Controller/ClassApiController.php create mode 100644 Tests/Functional/Controller/ClassApiController80.php create mode 100644 Tests/Functional/Controller/ClassApiController81.php delete mode 100644 Tests/Functional/Controller/InvokableController.php create mode 100644 Tests/Functional/Controller/InvokableController80.php create mode 100644 Tests/Functional/Controller/InvokableController81.php diff --git a/Tests/Functional/Controller/ClassApiController.php b/Tests/Functional/Controller/ClassApiController.php deleted file mode 100644 index b85e731b2..000000000 --- a/Tests/Functional/Controller/ClassApiController.php +++ /dev/null @@ -1,48 +0,0 @@ - Date: Sat, 16 Dec 2023 16:04:16 +0100 Subject: [PATCH 25/54] fix: ArrayItemsErrorController php 7 failure --- .../Controller/ArrayItemsErrorController.php | 30 +++------------- .../ArrayItemsErrorController80.php | 34 +++++++++++++++++++ .../ArrayItemsErrorController81.php | 26 ++++++++++++++ 3 files changed, 64 insertions(+), 26 deletions(-) create mode 100644 Tests/Functional/Controller/ArrayItemsErrorController80.php create mode 100644 Tests/Functional/Controller/ArrayItemsErrorController81.php diff --git a/Tests/Functional/Controller/ArrayItemsErrorController.php b/Tests/Functional/Controller/ArrayItemsErrorController.php index 29ce11c09..972598e53 100644 --- a/Tests/Functional/Controller/ArrayItemsErrorController.php +++ b/Tests/Functional/Controller/ArrayItemsErrorController.php @@ -11,41 +11,19 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArrayItemsError\Foo; -use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @Route(host="api.example.com") */ - class ArrayItemsErrorController + class ArrayItemsErrorController extends ArrayItemsErrorController80 { - /** - * @Route("/api/error", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=Foo::class) - * ) - */ - public function errorAction() - { - } } } else { #[Route(host: 'api.example.com')] - class ArrayItemsErrorController + class ArrayItemsErrorController extends ArrayItemsErrorController81 { - #[Route('/api/error', methods: ['GET'])] - #[OAT\Response(response: 200, description: 'Success', content: new Model(type: Foo::class))] - public function errorAction() - { - } } } diff --git a/Tests/Functional/Controller/ArrayItemsErrorController80.php b/Tests/Functional/Controller/ArrayItemsErrorController80.php new file mode 100644 index 000000000..c0ba4404a --- /dev/null +++ b/Tests/Functional/Controller/ArrayItemsErrorController80.php @@ -0,0 +1,34 @@ + Date: Sat, 16 Dec 2023 16:06:42 +0100 Subject: [PATCH 26/54] feat: re-enable symfony 7 compatible packages --- Tests/Functional/TestKernel.php | 125 +++++++++++++++----------------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index df69567a0..e385bc84c 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -61,16 +61,19 @@ public function registerBundles(): iterable new TestBundle(), ]; - if (self::MAJOR_VERSION < 7) { + if (class_exists(SensioFrameworkExtraBundle::class)) { $bundles[] = new SensioFrameworkExtraBundle(); + } + + if (class_exists(FOSRestBundle::class)) { $bundles[] = new FOSRestBundle(); + } - if ($this->flags & self::USE_JMS) { - $bundles[] = new JMSSerializerBundle(); + if ($this->flags & self::USE_JMS) { + $bundles[] = new JMSSerializerBundle(); - if ($this->flags & self::USE_BAZINGA) { - $bundles[] = new BazingaHateoasBundle(); - } + if ($this->flags & self::USE_BAZINGA) { + $bundles[] = new BazingaHateoasBundle(); } } @@ -86,22 +89,20 @@ protected function configureRoutes($routes) } if ($this->flags & self::ERROR_ARRAY_ITEMS) { - $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', self::MAJOR_VERSION < 7 ? 'annotation' : 'attribute'); + $this->import($routes, __DIR__.'/Controller/ArrayItemsErrorController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); } - if (self::MAJOR_VERSION < 7) { - if ($this->flags & self::USE_JMS) { - $this->import($routes, __DIR__.'/Controller/JMSController.php', '/', 'annotation'); - } + if ($this->flags & self::USE_JMS) { + $this->import($routes, __DIR__.'/Controller/JMSController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); + } - if ($this->flags & self::USE_BAZINGA) { - $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', 'annotation'); + if ($this->flags & self::USE_BAZINGA) { + $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', 'annotation'); - try { - new \ReflectionMethod(Embedded::class, 'getType'); - $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', 'annotation'); - } catch (\ReflectionException $e) { - } + try { + new \ReflectionMethod(Embedded::class, 'getType'); + $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', 'annotation'); + } catch (\ReflectionException $e) { } } } @@ -192,53 +193,6 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load } } - $models = [ - [ - 'alias' => 'PrivateProtectedExposure', - 'type' => PrivateProtectedExposure::class, - ], - [ - 'alias' => 'SymfonyConstraintsTestGroup', - 'type' => SymfonyConstraintsWithValidationGroups::class, - 'groups' => ['test'], - ], - [ - 'alias' => 'SymfonyConstraintsDefaultGroup', - 'type' => SymfonyConstraintsWithValidationGroups::class, - 'groups' => null, - ], - ]; - - if (self::MAJOR_VERSION < 7) { - $models = [ - ...$models, - [ - 'alias' => 'JMSPicture_mini', - 'type' => JMSPicture::class, - 'groups' => ['mini'], - ], - [ - 'alias' => 'BazingaUser_grouped', - 'type' => BazingaUser::class, - 'groups' => ['foo'], - ], - [ - 'alias' => 'JMSComplex', - 'type' => JMSComplex::class, - 'groups' => [ - 'list', - 'details', - 'User' => ['list'], - ], - ], - [ - 'alias' => 'JMSComplexDefault', - 'type' => JMSComplex::class, - 'groups' => null, - ], - ]; - } - // Filter routes $c->loadFromExtension('nelmio_api_doc', [ 'use_validation_groups' => boolval($this->flags & self::USE_VALIDATION_GROUPS), @@ -311,7 +265,46 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], ], 'models' => [ - 'names' => $models, + 'names' => [ + [ + 'alias' => 'PrivateProtectedExposure', + 'type' => PrivateProtectedExposure::class, + ], + [ + 'alias' => 'JMSPicture_mini', + 'type' => JMSPicture::class, + 'groups' => ['mini'], + ], + [ + 'alias' => 'BazingaUser_grouped', + 'type' => BazingaUser::class, + 'groups' => ['foo'], + ], + [ + 'alias' => 'JMSComplex', + 'type' => JMSComplex::class, + 'groups' => [ + 'list', + 'details', + 'User' => ['list'], + ], + ], + [ + 'alias' => 'JMSComplexDefault', + 'type' => JMSComplex::class, + 'groups' => null, + ], + [ + 'alias' => 'SymfonyConstraintsTestGroup', + 'type' => SymfonyConstraintsWithValidationGroups::class, + 'groups' => ['test'], + ], + [ + 'alias' => 'SymfonyConstraintsDefaultGroup', + 'type' => SymfonyConstraintsWithValidationGroups::class, + 'groups' => null, + ], + ], ], ]); From ba51c10b0dab2d8637b0701170df080f05a73534 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 17:26:20 +0100 Subject: [PATCH 27/54] feat: JMS tests for attributes --- Tests/Functional/Controller/JMSController.php | 143 +--------- .../Functional/Controller/JMSController80.php | 154 +++++++++++ .../Functional/Controller/JMSController81.php | 122 +++++++++ Tests/Functional/Entity/JMSComplex.php | 68 ++--- Tests/Functional/Entity/JMSComplex80.php | 61 +++++ Tests/Functional/Entity/JMSComplex81.php | 43 +++ Tests/Functional/Entity/JMSDualComplex.php | 30 +-- Tests/Functional/Entity/JMSDualComplex80.php | 34 +++ Tests/Functional/Entity/JMSDualComplex81.php | 28 ++ .../Entity/JMSNamingStrategyConstraints.php | 27 +- .../Entity/JMSNamingStrategyConstraints80.php | 43 +++ .../Entity/JMSNamingStrategyConstraints81.php | 38 +++ Tests/Functional/Entity/JMSNote.php | 32 +-- Tests/Functional/Entity/JMSNote80.php | 36 +++ Tests/Functional/Entity/JMSNote81.php | 29 +++ Tests/Functional/Entity/JMSUser.php | 233 +---------------- Tests/Functional/Entity/JMSUser80.php | 245 ++++++++++++++++++ Tests/Functional/Entity/JMSUser81.php | 168 ++++++++++++ .../Functional/Entity/NestedGroup/JMSChat.php | 30 +-- .../Entity/NestedGroup/JMSChat80.php | 36 +++ .../Entity/NestedGroup/JMSChat81.php | 29 +++ .../Entity/NestedGroup/JMSChatFriend.php | 41 +-- .../Entity/NestedGroup/JMSChatFriend80.php | 47 ++++ .../Entity/NestedGroup/JMSChatFriend81.php | 35 +++ .../Entity/NestedGroup/JMSChatRoom.php | 42 +-- .../Entity/NestedGroup/JMSChatRoom80.php | 47 ++++ .../Entity/NestedGroup/JMSChatRoom81.php | 35 +++ .../Entity/NestedGroup/JMSChatRoomUser.php | 34 +-- .../Entity/NestedGroup/JMSChatRoomUser80.php | 38 +++ .../Entity/NestedGroup/JMSChatRoomUser81.php | 27 ++ .../Entity/NestedGroup/JMSChatUser.php | 41 +-- .../Entity/NestedGroup/JMSChatUser80.php | 45 ++++ .../Entity/NestedGroup/JMSChatUser81.php | 34 +++ .../Entity/NestedGroup/JMSPicture.php | 31 +-- .../Entity/NestedGroup/JMSPicture80.php | 38 +++ .../Entity/NestedGroup/JMSPicture81.php | 30 +++ Tests/Functional/Entity/VirtualProperty.php | 55 +--- Tests/Functional/Entity/VirtualProperty80.php | 69 +++++ Tests/Functional/Entity/VirtualProperty81.php | 59 +++++ Tests/Functional/JMSFunctionalTest.php | 4 - Tests/Functional/TestKernel.php | 12 +- 41 files changed, 1700 insertions(+), 693 deletions(-) create mode 100644 Tests/Functional/Controller/JMSController80.php create mode 100644 Tests/Functional/Controller/JMSController81.php create mode 100644 Tests/Functional/Entity/JMSComplex80.php create mode 100644 Tests/Functional/Entity/JMSComplex81.php create mode 100644 Tests/Functional/Entity/JMSDualComplex80.php create mode 100644 Tests/Functional/Entity/JMSDualComplex81.php create mode 100644 Tests/Functional/Entity/JMSNamingStrategyConstraints80.php create mode 100644 Tests/Functional/Entity/JMSNamingStrategyConstraints81.php create mode 100644 Tests/Functional/Entity/JMSNote80.php create mode 100644 Tests/Functional/Entity/JMSNote81.php create mode 100644 Tests/Functional/Entity/JMSUser80.php create mode 100644 Tests/Functional/Entity/JMSUser81.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChat80.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChat81.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatFriend80.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatFriend81.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatRoom80.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatRoom81.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatRoomUser80.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatRoomUser81.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatUser80.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSChatUser81.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSPicture80.php create mode 100644 Tests/Functional/Entity/NestedGroup/JMSPicture81.php create mode 100644 Tests/Functional/Entity/VirtualProperty80.php create mode 100644 Tests/Functional/Entity/VirtualProperty81.php diff --git a/Tests/Functional/Controller/JMSController.php b/Tests/Functional/Controller/JMSController.php index 2f377c7aa..4cf8b5d51 100644 --- a/Tests/Functional/Controller/JMSController.php +++ b/Tests/Functional/Controller/JMSController.php @@ -11,147 +11,20 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSDualComplex; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNamingStrategyConstraints; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChat; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatRoomUser; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatUser; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSPicture; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\VirtualProperty; -use OpenApi\Annotations as OA; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; -/** - * @Route(host="api.example.com") - */ -class JMSController -{ - /** - * @Route("/api/jms", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSUser::class) - * ) - */ - public function userAction() - { - } - - /** - * @Route("/api/yaml", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=VirtualProperty::class) - * ) - */ - public function yamlAction() - { - } - - /** - * @Route("/api/jms_complex", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSComplex::class, groups={"list", "details", "User" : {"list"}}) - * ) - */ - public function complexAction() - { - } - - /** - * @Route("/api/jms_complex_dual", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSDualComplex::class, groups={"Default", "complex" : {"User" : {"details"}}}) - * ) - */ - public function complexDualAction() - { - } - - /** - * @Route("/api/jms_naming_strategy", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSNamingStrategyConstraints::class, groups={"Default"}) - * ) - */ - public function namingStrategyConstraintsAction() - { - } - - /** - * @Route("/api/jms_chat", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSChat::class, groups={"Default", "members" : {"mini"}}) - * ) - */ - public function chatAction() - { - } - - /** - * @Route("/api/jms_picture", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSPicture::class, groups={"mini"}) - * ) - */ - public function pictureAction() - { - } - +if (TestKernel::isAnnotationsAvailable()) { /** - * @Route("/api/jms_mini_user", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSChatUser::class, groups={"mini"}) - * ) + * @Route(host="api.example.com") */ - public function minUserAction() + class JMSController extends JMSController80 { } - - /** - * @Route("/api/jms_mini_user_nested", methods={"GET"}) - * - * @OA\Response( - * response=200, - * description="Success", - * - * @Model(type=JMSChatRoomUser::class, groups={"mini", "friend": {"living":{"Default"}}}) - * ) - */ - public function minUserNestedAction() +} else { + #[Route(host: "api.example.com")] + class JMSController extends JMSController81 { } } + diff --git a/Tests/Functional/Controller/JMSController80.php b/Tests/Functional/Controller/JMSController80.php new file mode 100644 index 000000000..e7f42d49b --- /dev/null +++ b/Tests/Functional/Controller/JMSController80.php @@ -0,0 +1,154 @@ + ["list"]]) + )] + public function complexAction() + { + } + + #[Route("/api/jms_complex_dual", methods: ["GET"])] + #[OA\Response( + response: 200, + description: "Success", + content: new Model( + type: JMSDualComplex::class, + groups: ["Default", "complex" => ["User" => ["details"]]]) + )] + public function complexDualAction() + { + } + + #[Route("/api/jms_naming_strategy", methods: ["GET"])] + #[OA\Response( + response: 200, + description: "Success", + content: new Model(type: JMSNamingStrategyConstraints::class, groups: ["Default"]) + )] + public function namingStrategyConstraintsAction() + { + } + + #[Route("/api/jms_chat", methods: ["GET"])] + #[OA\Response( + response: 200, + description: "Success", + content: new Model(type: JMSChat::class, groups: ["Default", "members" => ["mini"]]) + )] + public function chatAction() + { + } + + #[Route("/api/jms_picture", methods: ["GET"])] + #[OA\Response( + response: 200, + description: "Success", + content: new Model(type: JMSPicture::class, groups: ["mini"]) + )] + public function pictureAction() + { + } + + #[Route("/api/jms_mini_user", methods: ["GET"])] + #[OA\Response( + response: 200, + description: "Success", + content: new Model(type: JMSChatUser::class, groups: ["mini"]) + )] + public function minUserAction() + { + } + + #[Route("/api/jms_mini_user_nested", methods: ["GET"])] + #[OA\Response( + response: 200, + description: "Success", + content: new Model(type: JMSChatRoomUser::class, groups: ["mini", "friend" => ["living" => ["Default"]]]) + )] + public function minUserNestedAction() + { + } +} diff --git a/Tests/Functional/Entity/JMSComplex.php b/Tests/Functional/Entity/JMSComplex.php index fcc7d199f..e24fd16ec 100644 --- a/Tests/Functional/Entity/JMSComplex.php +++ b/Tests/Functional/Entity/JMSComplex.php @@ -13,58 +13,34 @@ use JMS\Serializer\Annotation as Serializer; use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -/** - * @Serializer\ExclusionPolicy("all") - * - * @OA\Schema( - * required={"id", "user"}, - * - * @OA\Property(property="virtual", ref=@Model(type=JMSUser::class)) - * ) - */ -class JMSComplex -{ - /** - * @Serializer\Type("integer") - * - * @Serializer\Expose - * - * @Serializer\Groups({"list"}) - */ - private $id; - - /** - * @OA\Property(ref=@Model(type=JMSUser::class)) - * - * @Serializer\Expose - * - * @Serializer\Groups({"details"}) - * - * @Serializer\SerializedName("user") - */ - private $User; - +if (TestKernel::isAnnotationsAvailable()) { /** - * @Serializer\Type("string") + * @Serializer\ExclusionPolicy("all") * - * @Serializer\Expose + * @OA\Schema( + * required={"id", "user"}, * - * @Serializer\Groups({"list"}) + * @OA\Property(property="virtual", ref=@Model(type=JMSUser::class)) + * ) */ - private $name; - - /** - * @Serializer\VirtualProperty - * - * @Serializer\Expose - * - * @Serializer\Groups({"list"}) - * - * @OA\Property(ref=@Model(type=JMSUser::class)) - */ - public function getVirtualFriend() + class JMSComplex extends JMSComplex80 + { + } +} else { + #[Serializer\ExclusionPolicy("all")] + #[\OpenApi\Attributes\Schema( + required: ["id", "user"], + properties: [ + new \OpenApi\Attributes\Property( + property: "virtual", + ref: new Model(type: JMSUser::class) + ), + ], + )] + class JMSComplex extends JMSComplex81 { } } diff --git a/Tests/Functional/Entity/JMSComplex80.php b/Tests/Functional/Entity/JMSComplex80.php new file mode 100644 index 000000000..1a2ea6b1c --- /dev/null +++ b/Tests/Functional/Entity/JMSComplex80.php @@ -0,0 +1,61 @@ +some_weird_named_property; } - - public function setSomeWeirdNamedProperty(string $some_weird_named_property) +} else { + class JMSNamingStrategyConstraints extends JMSNamingStrategyConstraints81 { - $this->some_weird_named_property = $some_weird_named_property; } } diff --git a/Tests/Functional/Entity/JMSNamingStrategyConstraints80.php b/Tests/Functional/Entity/JMSNamingStrategyConstraints80.php new file mode 100644 index 000000000..d0d24b90f --- /dev/null +++ b/Tests/Functional/Entity/JMSNamingStrategyConstraints80.php @@ -0,0 +1,43 @@ +some_weird_named_property; + } + + public function setSomeWeirdNamedProperty(string $some_weird_named_property) + { + $this->some_weird_named_property = $some_weird_named_property; + } +} diff --git a/Tests/Functional/Entity/JMSNamingStrategyConstraints81.php b/Tests/Functional/Entity/JMSNamingStrategyConstraints81.php new file mode 100644 index 000000000..5184778a0 --- /dev/null +++ b/Tests/Functional/Entity/JMSNamingStrategyConstraints81.php @@ -0,0 +1,38 @@ +some_weird_named_property; + } + + public function setSomeWeirdNamedProperty(string $some_weird_named_property) + { + $this->some_weird_named_property = $some_weird_named_property; + } +} diff --git a/Tests/Functional/Entity/JMSNote.php b/Tests/Functional/Entity/JMSNote.php index 1ec6abb3c..204fd93b5 100644 --- a/Tests/Functional/Entity/JMSNote.php +++ b/Tests/Functional/Entity/JMSNote.php @@ -11,26 +11,14 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use JMS\Serializer\Annotation as Serializer; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; -/** - * JMSNote. - * - * @Serializer\ExclusionPolicy("all") - */ -class JMSNote -{ - /** - * @Serializer\Type("string") - * - * @Serializer\Expose - */ - private $long; - - /** - * @Serializer\Type("int") - * - * @Serializer\Expose - */ - private $short; -} +if (TestKernel::isAnnotationsAvailable()) { + class JMSNote extends JMSNote80 + { + } +} else { + class JMSNote extends JMSNote81 + { + } +} \ No newline at end of file diff --git a/Tests/Functional/Entity/JMSNote80.php b/Tests/Functional/Entity/JMSNote80.php new file mode 100644 index 000000000..f1e384e43 --- /dev/null +++ b/Tests/Functional/Entity/JMSNote80.php @@ -0,0 +1,36 @@ +") - * - * @Serializer\Accessor(getter="getRoles", setter="setRoles") - * - * @Serializer\Expose - * - * @OA\Property(default = {"user"}, description = "Roles list", example="[""ADMIN"",""SUPERUSER""]", title="roles") - */ - private $roles; - - /** - * User Location. - * - * @Serializer\Type("string") - * - * @Serializer\Expose - */ - private $location; - - /** - * @Serializer\Type("string") - */ - private $password; - - /** - * @OA\Property(property="last_update", type="date") - * - * @Serializer\Expose - */ - private $updatedAt; - - /** - * Ignored as the JMS serializer can't detect its type. - * - * @Serializer\Expose - */ - private $createdAt; - - /** - * @Serializer\Type("array") - * - * @Serializer\Expose - */ - private $friends; - - /** - * @Serializer\Type("array") - * - * @Serializer\Expose - */ - private $indexedFriends; - - /** - * @Serializer\Type("array") - * - * @Serializer\Expose - */ - private $favoriteDates; - - /** - * @Serializer\Type(Nelmio\ApiDocBundle\Tests\Functional\Entity\CustomDateTime::class) - * - * @Serializer\Expose - */ - private $customDate; - - /** - * @Serializer\Type("integer") - * - * @Serializer\Expose - * - * @Serializer\SerializedName("friendsNumber") - * - * @OA\Property(type = "string", minLength = 1, maxLength = 100) - */ - private $friendsNumber; - - /** - * @Serializer\Type(User::class) - * - * @Serializer\Expose - */ - private $bestFriend; - - /** - * Whether this user is enabled or disabled. - * - * Only enabled users may be used in actions. - * - * @var string - * - * @Serializer\Type("string") - * - * @Serializer\Expose - * - * @OA\Property(enum = {"disabled", "enabled"}) - */ - private $status; - - /** - * JMS custom types handled via Custom Type Handlers. - * - * @var string - * - * @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerDefined") - * - * @Serializer\Expose - */ - private $virtualType1; - - /** - * JMS custom types handled via Custom Type Handlers. - * - * @var string - * - * @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerNotDefined") - * - * @Serializer\Expose - */ - private $virtualType2; - - /** - * @Serializer\Type("array>") - * - * @Serializer\Expose - */ - private $latLonHistory; - - /** - * @Serializer\Type("array") - * - * @Serializer\Expose - */ - private $freeFormObject; - - /** - * @Serializer\Type("array") - * - * @Serializer\Expose - */ - private $freeFormObjectWithoutType; - - /** - * @Serializer\Type("array>") - * - * @Serializer\Expose - */ - private $deepObject; - - /** - * @Serializer\Type("array>") - * - * @Serializer\Expose - */ - private $deepObjectWithItems; - - /** - * @Serializer\Type("array>>") - * - * @Serializer\Expose - */ - private $deepFreeFormObjectCollection; - - /** - * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNote") - * - * @Serializer\Inline() - * - * @Serializer\Expose - */ - private $notes; - - public function setRoles($roles) +if (TestKernel::isAnnotationsAvailable()) { + class JMSUser extends JMSUser80 { } - - public function getRoles() - { - } - - public function setDummy(Dummy $dummy) +} else { + class JMSUser extends JMSUser81 { } -} +} \ No newline at end of file diff --git a/Tests/Functional/Entity/JMSUser80.php b/Tests/Functional/Entity/JMSUser80.php new file mode 100644 index 000000000..6a6a7ce8c --- /dev/null +++ b/Tests/Functional/Entity/JMSUser80.php @@ -0,0 +1,245 @@ +") + * + * @Serializer\Accessor(getter="getRoles", setter="setRoles") + * + * @Serializer\Expose + * + * @OA\Property(default = {"user"}, description = "Roles list", example="[""ADMIN"",""SUPERUSER""]", title="roles") + */ + private $roles; + + /** + * User Location. + * + * @Serializer\Type("string") + * + * @Serializer\Expose + */ + private $location; + + /** + * @Serializer\Type("string") + */ + private $password; + + /** + * @OA\Property(property="last_update", type="date") + * + * @Serializer\Expose + */ + private $updatedAt; + + /** + * Ignored as the JMS serializer can't detect its type. + * + * @Serializer\Expose + */ + private $createdAt; + + /** + * @Serializer\Type("array") + * + * @Serializer\Expose + */ + private $friends; + + /** + * @Serializer\Type("array") + * + * @Serializer\Expose + */ + private $indexedFriends; + + /** + * @Serializer\Type("array") + * + * @Serializer\Expose + */ + private $favoriteDates; + + /** + * @Serializer\Type(Nelmio\ApiDocBundle\Tests\Functional\Entity\CustomDateTime::class) + * + * @Serializer\Expose + */ + private $customDate; + + /** + * @Serializer\Type("integer") + * + * @Serializer\Expose + * + * @Serializer\SerializedName("friendsNumber") + * + * @OA\Property(type = "string", minLength = 1, maxLength = 100) + */ + private $friendsNumber; + + /** + * @Serializer\Type(User::class) + * + * @Serializer\Expose + */ + private $bestFriend; + + /** + * Whether this user is enabled or disabled. + * + * Only enabled users may be used in actions. + * + * @var string + * + * @Serializer\Type("string") + * + * @Serializer\Expose + * + * @OA\Property(enum = {"disabled", "enabled"}) + */ + private $status; + + /** + * JMS custom types handled via Custom Type Handlers. + * + * @var string + * + * @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerDefined") + * + * @Serializer\Expose + */ + private $virtualType1; + + /** + * JMS custom types handled via Custom Type Handlers. + * + * @var string + * + * @Serializer\Type("VirtualTypeClassDoesNotExistsHandlerNotDefined") + * + * @Serializer\Expose + */ + private $virtualType2; + + /** + * @Serializer\Type("array>") + * + * @Serializer\Expose + */ + private $latLonHistory; + + /** + * @Serializer\Type("array") + * + * @Serializer\Expose + */ + private $freeFormObject; + + /** + * @Serializer\Type("array") + * + * @Serializer\Expose + */ + private $freeFormObjectWithoutType; + + /** + * @Serializer\Type("array>") + * + * @Serializer\Expose + */ + private $deepObject; + + /** + * @Serializer\Type("array>") + * + * @Serializer\Expose + */ + private $deepObjectWithItems; + + /** + * @Serializer\Type("array>>") + * + * @Serializer\Expose + */ + private $deepFreeFormObjectCollection; + + /** + * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNote") + * + * @Serializer\Inline() + * + * @Serializer\Expose + */ + private $notes; + + public function setRoles($roles) + { + } + + public function getRoles() + { + } + + public function setDummy(Dummy $dummy) + { + } +} diff --git a/Tests/Functional/Entity/JMSUser81.php b/Tests/Functional/Entity/JMSUser81.php new file mode 100644 index 000000000..d046f1932 --- /dev/null +++ b/Tests/Functional/Entity/JMSUser81.php @@ -0,0 +1,168 @@ +")] + #[Serializer\Accessor(getter: "getRoles", setter: "setRoles")] + #[Serializer\Expose] + #[OA\Property(default: ["user"], description: "Roles list", example: '["ADMIN","SUPERUSER"]', title: "roles")] + private $roles; + + /** + * User Location. + */ + #[Serializer\Type("string")] + #[Serializer\Expose] + private $location; + + #[Serializer\Type("string")] + private $password; + + #[OA\Property(property: "last_update", type: "date")] + #[Serializer\Expose] + private $updatedAt; + + /** + * Ignored as the JMS serializer can't detect its type. + */ + #[Serializer\Expose] + private $createdAt; + + #[Serializer\Type("array")] + #[Serializer\Expose] + private $friends; + + #[Serializer\Type("array")] + #[Serializer\Expose] + private $indexedFriends; + + #[Serializer\Type("array")] + #[Serializer\Expose] + private $favoriteDates; + + #[Serializer\Type(CustomDateTime::class)] + #[Serializer\Expose] + private $customDate; + + #[Serializer\Type("integer")] + #[Serializer\Expose] + #[Serializer\SerializedName("friendsNumber")] + #[OA\Property(type: "string", minLength: 1, maxLength: 100)] + private $friendsNumber; + + #[Serializer\Type(User::class)] + #[Serializer\Expose] + private $bestFriend; + + /** + * Whether this user is enabled or disabled. + * + * Only enabled users may be used in actions. + * + * @var string + */ + #[Serializer\Type("string")] + #[Serializer\Expose] + #[OA\Property(enum: ["disabled", "enabled"])] + private $status; + + /** + * JMS custom types handled via Custom Type Handlers. + * + * @var string + */ + #[Serializer\Type("VirtualTypeClassDoesNotExistsHandlerDefined")] + #[Serializer\Expose] + private $virtualType1; + + /** + * JMS custom types handled via Custom Type Handlers. + * + * @var string + */ + #[Serializer\Type("VirtualTypeClassDoesNotExistsHandlerNotDefined")] + #[Serializer\Expose] + private $virtualType2; + + #[Serializer\Type("array>")] + #[Serializer\Expose] + private $latLonHistory; + + #[Serializer\Type("array")] + #[Serializer\Expose] + private $freeFormObject; + + #[Serializer\Type("array")] + #[Serializer\Expose] + private $freeFormObjectWithoutType; + + #[Serializer\Type("array>")] + #[Serializer\Expose] + private $deepObject; + + #[Serializer\Type("array>")] + #[Serializer\Expose] + private $deepObjectWithItems; + + #[Serializer\Type("array>>")] + #[Serializer\Expose] + private $deepFreeFormObjectCollection; + + #[Serializer\Type(JMSNote::class)] + #[Serializer\Inline] + #[Serializer\Expose] + private $notes; + + public function setRoles($roles) + { + } + + public function getRoles() + { + } + + public function setDummy(Dummy $dummy) + { + } +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChat.php b/Tests/Functional/Entity/NestedGroup/JMSChat.php index a36da193f..d9f1318b0 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChat.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChat.php @@ -11,26 +11,14 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup; -use JMS\Serializer\Annotation as Serializer; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; -/** - * User. - * - * @Serializer\ExclusionPolicy("all") - */ -class JMSChat -{ - /** - * @Serializer\Type("integer") - * - * @Serializer\Expose - */ - private $id; - - /** - * @Serializer\Type("array") - * - * @Serializer\Expose - */ - private $members; +if (TestKernel::isAnnotationsAvailable()) { + class JMSChat extends JMSChat80 + { + } +} else { + class JMSChat extends JMSChat81 + { + } } diff --git a/Tests/Functional/Entity/NestedGroup/JMSChat80.php b/Tests/Functional/Entity/NestedGroup/JMSChat80.php new file mode 100644 index 000000000..34be4ab76 --- /dev/null +++ b/Tests/Functional/Entity/NestedGroup/JMSChat80.php @@ -0,0 +1,36 @@ +") + * + * @Serializer\Expose + */ + private $members; +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChat81.php b/Tests/Functional/Entity/NestedGroup/JMSChat81.php new file mode 100644 index 000000000..9c44322b7 --- /dev/null +++ b/Tests/Functional/Entity/NestedGroup/JMSChat81.php @@ -0,0 +1,29 @@ +')] + #[Serializer\Expose] + private $members; +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php b/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php index fd0f7d3f4..dca4ece65 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatFriend.php @@ -11,37 +11,14 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup; -use JMS\Serializer\Annotation as Serializer; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; -/** - * User. - * - * @Serializer\ExclusionPolicy("all") - */ -class JMSChatFriend -{ - /** - * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatRoom") - * - * @Serializer\Expose - * - * @Serializer\Groups({"mini"}) - */ - private $room; - - /** - * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatLivingRoom") - * - * @Serializer\Expose - * - * @Serializer\Groups({"Default", "mini"}) - */ - private $living; - - /** - * @Serializer\Type("Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSChatRoom") - * - * @Serializer\Expose - */ - private $dining; +if (TestKernel::isAnnotationsAvailable()) { + class JMSChatFriend extends JMSChatFriend80 + { + } +} else { + class JMSChatFriend extends JMSChatFriend81 + { + } } diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatFriend80.php b/Tests/Functional/Entity/NestedGroup/JMSChatFriend80.php new file mode 100644 index 000000000..65a008849 --- /dev/null +++ b/Tests/Functional/Entity/NestedGroup/JMSChatFriend80.php @@ -0,0 +1,47 @@ +") - * - * @Serializer\Expose - */ - private $allPictures; -} +if (TestKernel::isAnnotationsAvailable()) { + class JMSChatUser extends JMSChatUser80 + { + } +} else { + class JMSChatUser extends JMSChatUser81 + { + } +} \ No newline at end of file diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatUser80.php b/Tests/Functional/Entity/NestedGroup/JMSChatUser80.php new file mode 100644 index 000000000..487947fe5 --- /dev/null +++ b/Tests/Functional/Entity/NestedGroup/JMSChatUser80.php @@ -0,0 +1,45 @@ +") + * + * @Serializer\Expose + */ + private $allPictures; +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php b/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php new file mode 100644 index 000000000..834ceb728 --- /dev/null +++ b/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php @@ -0,0 +1,34 @@ +')] + #[Serializer\Expose] + private $allPictures; +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSPicture.php b/Tests/Functional/Entity/NestedGroup/JMSPicture.php index 3a2d70d5c..98dbd8f2f 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSPicture.php +++ b/Tests/Functional/Entity/NestedGroup/JMSPicture.php @@ -11,28 +11,15 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup; -use JMS\Serializer\Annotation as Serializer; -/** - * User. - * - * @Serializer\ExclusionPolicy("all") - */ -class JMSPicture -{ - /** - * @Serializer\Type("integer") - * - * @Serializer\Expose - */ - private $id; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; - /** - * @Serializer\Type("integer") - * - * @Serializer\Expose - * - * @Serializer\Groups({"mini"}) - */ - private $onlyDirectPictureMini; +if (TestKernel::isAnnotationsAvailable()) { + class JMSPicture extends JMSPicture80 + { + } +} else { + class JMSPicture extends JMSPicture81 + { + } } diff --git a/Tests/Functional/Entity/NestedGroup/JMSPicture80.php b/Tests/Functional/Entity/NestedGroup/JMSPicture80.php new file mode 100644 index 000000000..0a13e5ad1 --- /dev/null +++ b/Tests/Functional/Entity/NestedGroup/JMSPicture80.php @@ -0,0 +1,38 @@ +user = new User(); - $this->user->setEmail('dummy@test.com'); } - - public function __call(string $name, array $arguments) +} else { + class VirtualProperty extends VirtualProperty81 { - if ('getFoo' === $name || 'setFoo' === $name) { - return 'Success'; - } - - throw new \LogicException(sprintf('%s::__call does not implement this function.', __CLASS__)); } -} +} \ No newline at end of file diff --git a/Tests/Functional/Entity/VirtualProperty80.php b/Tests/Functional/Entity/VirtualProperty80.php new file mode 100644 index 000000000..6aa90c253 --- /dev/null +++ b/Tests/Functional/Entity/VirtualProperty80.php @@ -0,0 +1,69 @@ +user = new User(); + $this->user->setEmail('dummy@test.com'); + } + + public function __call(string $name, array $arguments) + { + if ('getFoo' === $name || 'setFoo' === $name) { + return 'Success'; + } + + throw new LogicException(sprintf('%s::__call does not implement this function.', __CLASS__)); + } +} diff --git a/Tests/Functional/Entity/VirtualProperty81.php b/Tests/Functional/Entity/VirtualProperty81.php new file mode 100644 index 000000000..aac0839e1 --- /dev/null +++ b/Tests/Functional/Entity/VirtualProperty81.php @@ -0,0 +1,59 @@ +user = new User(); + $this->user->setEmail('dummy@test.com'); + } + + public function __call(string $name, array $arguments) + { + if ('getFoo' === $name || 'setFoo' === $name) { + return 'Success'; + } + + throw new LogicException(sprintf('%s::__call does not implement this function.', __CLASS__)); + } +} diff --git a/Tests/Functional/JMSFunctionalTest.php b/Tests/Functional/JMSFunctionalTest.php index 80c91c9c3..550350a5b 100644 --- a/Tests/Functional/JMSFunctionalTest.php +++ b/Tests/Functional/JMSFunctionalTest.php @@ -20,10 +20,6 @@ protected function setUp(): void { parent::setUp(); - if (Kernel::MAJOR_VERSION >= 7) { - $this->markTestSkipped('JMS Serializer is not compatible with Symfony 7+'); - } - static::createClient([], ['HTTP_HOST' => 'api.example.com']); } diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index e385bc84c..940c502bc 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -37,10 +37,10 @@ class TestKernel extends Kernel { use MicroKernelTrait; - public const USE_JMS = 1; - public const USE_BAZINGA = 2; - public const ERROR_ARRAY_ITEMS = 4; - public const USE_VALIDATION_GROUPS = 8; + const USE_JMS = 1; + const USE_BAZINGA = 2; + const ERROR_ARRAY_ITEMS = 4; + const USE_VALIDATION_GROUPS = 8; private $flags; @@ -97,11 +97,11 @@ protected function configureRoutes($routes) } if ($this->flags & self::USE_BAZINGA) { - $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', 'annotation'); + $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); try { new \ReflectionMethod(Embedded::class, 'getType'); - $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', 'annotation'); + $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); } catch (\ReflectionException $e) { } } From e4892dfef967e21bd839353a9e0242c9e997f493 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 17:34:50 +0100 Subject: [PATCH 28/54] fix: isAnnotationsAvailable symfony version check --- Tests/Functional/TestKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 940c502bc..319a070a6 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -335,7 +335,7 @@ public function unserialize($str) public static function isAnnotationsAvailable(): bool { - if (Kernel::MAJOR_VERSION < 7) { + if (Kernel::MAJOR_VERSION >= 7) { return false; } From 452b6d2ad4b237c210ab560ff731fd3940934447 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 17:38:33 +0100 Subject: [PATCH 29/54] fix: ci no annotations reader found --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3c38154ec..f4300b420 100644 --- a/composer.json +++ b/composer.json @@ -54,7 +54,8 @@ "willdurand/hateoas-bundle": "^1.0|^2.0", "jms/serializer-bundle": "^2.3|^3.0|^4.0|^5.0@beta", "jms/serializer": "^1.14|^3.0", - "composer/package-versions-deprecated": "1.11.99.1" + "composer/package-versions-deprecated": "1.11.99.1", + "doctrine/annotations": "^2.0" }, "suggest": { "api-platform/core": "For using an API oriented framework.", From 7b0fc34ca1abc96bb54c41c9a9f8f6cf08cf822b Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 19:51:57 +0100 Subject: [PATCH 30/54] fix: JMS could not guess type --- Tests/Functional/Entity/JMSUser80.php | 2 +- Tests/Functional/Entity/JMSUser81.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Functional/Entity/JMSUser80.php b/Tests/Functional/Entity/JMSUser80.php index 6a6a7ce8c..19e7c458a 100644 --- a/Tests/Functional/Entity/JMSUser80.php +++ b/Tests/Functional/Entity/JMSUser80.php @@ -67,7 +67,7 @@ class JMSUser80 * * @OA\Property(default = {"user"}, description = "Roles list", example="[""ADMIN"",""SUPERUSER""]", title="roles") */ - private $roles; + protected $roles; /** * User Location. diff --git a/Tests/Functional/Entity/JMSUser81.php b/Tests/Functional/Entity/JMSUser81.php index d046f1932..52e6e4418 100644 --- a/Tests/Functional/Entity/JMSUser81.php +++ b/Tests/Functional/Entity/JMSUser81.php @@ -47,7 +47,7 @@ class JMSUser81 #[Serializer\Accessor(getter: "getRoles", setter: "setRoles")] #[Serializer\Expose] #[OA\Property(default: ["user"], description: "Roles list", example: '["ADMIN","SUPERUSER"]', title: "roles")] - private $roles; + protected $roles; /** * User Location. From 48e422ee68d573119203257a391f41b23cce14bc Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 19:57:13 +0100 Subject: [PATCH 31/54] fix: separate FOS test --- Tests/Functional/FOSRestTest.php | 6 ++++++ Tests/Functional/Resources/routes.yaml | 5 ----- Tests/Functional/TestKernel.php | 5 +++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index 0550c9336..c915cf44a 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -14,9 +14,15 @@ use OpenApi\Annotations as OA; use OpenApi\Generator; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelInterface; class FOSRestTest extends WebTestCase { + protected static function createKernel(array $options = []): KernelInterface + { + return new TestKernel(TestKernel::USE_FOSREST); + } + protected function setUp(): void { if (Kernel::MAJOR_VERSION >= 7) { diff --git a/Tests/Functional/Resources/routes.yaml b/Tests/Functional/Resources/routes.yaml index 85b08d734..d6cd8b82e 100644 --- a/Tests/Functional/Resources/routes.yaml +++ b/Tests/Functional/Resources/routes.yaml @@ -19,11 +19,6 @@ invokable: resource: ../Controller/InvokableController80.php type: annotation -fos_rest: - resource: ../Controller/FOSRestController.php - type: annotation - - api_platform: resource: . prefix: /api diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 319a070a6..89d9081c0 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -39,6 +39,7 @@ class TestKernel extends Kernel use MicroKernelTrait; const USE_JMS = 1; const USE_BAZINGA = 2; + const USE_FOSREST = 3; const ERROR_ARRAY_ITEMS = 4; const USE_VALIDATION_GROUPS = 8; @@ -105,6 +106,10 @@ protected function configureRoutes($routes) } catch (\ReflectionException $e) { } } + + if ($this->flags & self::USE_FOSREST) { + $this->import($routes, __DIR__.'/Controller/FOSRestController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); + } } /** From bc2d533ef96b26460cccc6bf77541390dccd752e Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sat, 16 Dec 2023 19:58:48 +0100 Subject: [PATCH 32/54] fix: only set enable_annotations on php 8+ --- Tests/Functional/TestKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 89d9081c0..ee69c559e 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -132,7 +132,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'test' => null, 'validation' => null, 'form' => null, - 'serializer' => self::isAnnotationsAvailable() ? ['enable_annotations' => true] : [] + [ + 'serializer' => PHP_VERSION_ID >= 80100 ? ['enable_annotations' => true] : [] + [ 'mapping' => [ 'paths' => [__DIR__.'/Resources/serializer/'], ], From 546a9187f1b5ec2f807c837c2640f1a5e5705427 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 01:39:13 +0100 Subject: [PATCH 33/54] ci: install doctrine/annotations --- .github/workflows/continuous-integration.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 7d21bd2d4..d73a2395c 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -26,16 +26,22 @@ jobs: include: - php-version: 7.2 composer-flags: "--prefer-lowest" + doctrine-annotations: true - php-version: 7.3 symfony-require: "5.4.*" + doctrine-annotations: true - php-version: 8.0 symfony-require: "5.4.*" + doctrine-annotations: true - php-version: 8.1 symfony-require: "5.4.*" + doctrine-annotations: true - php-version: 8.1 symfony-require: "6.3.*" + doctrine-annotations: true - php-version: 8.2 symfony-require: "7.0.*" + doctrine-annotations: false steps: - name: "Checkout" @@ -61,6 +67,11 @@ jobs: key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-composer- + - name: Install doctrine/annotations + if: matrix.doctrine-annotations == true + run: | + composer require doctrine/annotations --no-update + - name: Remove packages not compatible symfony 7 if: matrix.symfony-require == '7.0.*' run: | From 24ace89e9532e8a286a9a52293db5e6a8be7082e Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 01:41:44 +0100 Subject: [PATCH 34/54] fix: check kernel version --- Tests/Functional/TestKernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index ee69c559e..234e7be4c 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -132,7 +132,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'test' => null, 'validation' => null, 'form' => null, - 'serializer' => PHP_VERSION_ID >= 80100 ? ['enable_annotations' => true] : [] + [ + 'serializer' => PHP_VERSION_ID >= 80100 && Kernel::MAJOR_VERSION < 7 ? ['enable_annotations' => true] : [] + [ 'mapping' => [ 'paths' => [__DIR__.'/Resources/serializer/'], ], From 25d70a8fad81e190467b56686001ac301b0571ed Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 02:08:52 +0100 Subject: [PATCH 35/54] test: check if reader available --- Tests/Functional/BazingaFunctionalTest.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Tests/Functional/BazingaFunctionalTest.php b/Tests/Functional/BazingaFunctionalTest.php index 92df0d95a..d1b1beec1 100644 --- a/Tests/Functional/BazingaFunctionalTest.php +++ b/Tests/Functional/BazingaFunctionalTest.php @@ -19,13 +19,15 @@ class BazingaFunctionalTest extends WebTestCase { protected function setUp(): void { - if (Kernel::MAJOR_VERSION >= 7) { - $this->markTestSkipped('Not supported in symfony 7'); - } - parent::setUp(); static::createClient([], ['HTTP_HOST' => 'api.example.com']); + + try { + self::getContainer()->get('annotations.reader'); + } catch (\Throwable $e) { + $this->markTestSkipped('Hateoas requires doctrine/annotations'); + } } public function testModelComplexDocumentationBazinga() From e7b34086900b4abf712a11264f46f00934646cb5 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 02:10:36 +0100 Subject: [PATCH 36/54] test: symfony 5 always contains annotations --- Tests/Functional/TestKernel.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 234e7be4c..54cb11aef 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -340,6 +340,10 @@ public function unserialize($str) public static function isAnnotationsAvailable(): bool { + if (Kernel::MAJOR_VERSION <= 5) { + return true; + } + if (Kernel::MAJOR_VERSION >= 7) { return false; } From b3a4fbbc8fab6b3b6f4106d661372859b1013922 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 02:11:04 +0100 Subject: [PATCH 37/54] fix: php 7 failing on use statement for attributes --- Tests/Functional/Entity/Article.php | 4 ++-- .../Entity/EntityWithAlternateType.php | 7 +++--- .../Entity/EntityWithNullableSchemaSet.php | 17 +++++++------- .../Entity/EntityWithObjectType.php | 7 +++--- Tests/Functional/Entity/EntityWithRef.php | 7 +++--- .../Functional/Entity/SymfonyConstraints.php | 4 ++-- ...SymfonyConstraintsWithValidationGroups.php | 7 +++--- .../Entity/SymfonyDiscriminator.php | 4 ++-- Tests/Functional/Entity/User.php | 23 +++++++++---------- 9 files changed, 37 insertions(+), 43 deletions(-) diff --git a/Tests/Functional/Entity/Article.php b/Tests/Functional/Entity/Article.php index 359ffc828..c8568a257 100644 --- a/Tests/Functional/Entity/Article.php +++ b/Tests/Functional/Entity/Article.php @@ -11,10 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use Symfony\Component\HttpKernel\Kernel; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Serializer\Annotation\Groups; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @author Guilhem N. */ diff --git a/Tests/Functional/Entity/EntityWithAlternateType.php b/Tests/Functional/Entity/EntityWithAlternateType.php index 1c49ffe5c..cab6fdc03 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType.php +++ b/Tests/Functional/Entity/EntityWithAlternateType.php @@ -11,11 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @OA\Schema(type="array", @OA\Items(type="string")) */ @@ -35,7 +34,7 @@ public function getIterator(): \ArrayIterator } } } else { - #[OAT\Schema(type: 'array', items: new OAT\Items(type: 'string'))] + #[\OpenApi\Attributes\Schema(type: 'array', items: new \OpenApi\Attributes\Items(type: 'string'))] class EntityWithAlternateType implements \IteratorAggregate { /** diff --git a/Tests/Functional/Entity/EntityWithNullableSchemaSet.php b/Tests/Functional/Entity/EntityWithNullableSchemaSet.php index 6e8d64a89..acf2e51df 100644 --- a/Tests/Functional/Entity/EntityWithNullableSchemaSet.php +++ b/Tests/Functional/Entity/EntityWithNullableSchemaSet.php @@ -11,11 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { class EntityWithNullableSchemaSet { /** @@ -66,37 +65,37 @@ class EntityWithNullableSchemaSet /** * @var ?string */ - #[OAT\Property] + #[\OpenApi\Attributes\Property] public $nullablePropertyNullableNotSet; /** * @var ?string */ - #[OAT\Property(nullable: false)] + #[\OpenApi\Attributes\Property(nullable: false)] public $nullablePropertyNullableFalseSet; /** * @var ?string */ - #[OAT\Property(nullable: true)] + #[\OpenApi\Attributes\Property(nullable: true)] public $nullablePropertyNullableTrueSet; /** * @var string */ - #[OAT\Property] + #[\OpenApi\Attributes\Property] public $nonNullablePropertyNullableNotSet; /** * @var string */ - #[OAT\Property(nullable: false)] + #[\OpenApi\Attributes\Property(nullable: false)] public $nonNullablePropertyNullableFalseSet; /** * @var string */ - #[OAT\Property(nullable: true)] + #[\OpenApi\Attributes\Property(nullable: true)] public $nonNullablePropertyNullableTrueSet; } } diff --git a/Tests/Functional/Entity/EntityWithObjectType.php b/Tests/Functional/Entity/EntityWithObjectType.php index 10b8b2fee..05cea1716 100644 --- a/Tests/Functional/Entity/EntityWithObjectType.php +++ b/Tests/Functional/Entity/EntityWithObjectType.php @@ -11,11 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @OA\Schema(type="object") */ @@ -27,7 +26,7 @@ class EntityWithObjectType public $notIgnored = 'this should be read'; } } else { - #[OAT\Schema(type: 'object')] + #[\OpenApi\Attributes\Schema(type: 'object')] class EntityWithObjectType { /** diff --git a/Tests/Functional/Entity/EntityWithRef.php b/Tests/Functional/Entity/EntityWithRef.php index 6b04fa592..09e2efb26 100644 --- a/Tests/Functional/Entity/EntityWithRef.php +++ b/Tests/Functional/Entity/EntityWithRef.php @@ -11,11 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @OA\Schema(ref="#/components/schemas/Test") */ @@ -27,7 +26,7 @@ class EntityWithRef public $ignored = 'this property should be ignored because of the annotation above'; } } else { - #[OAT\Schema(ref: '#/components/schemas/Test')] + #[\OpenApi\Attributes\Schema(ref: '#/components/schemas/Test')] class EntityWithRef { /** diff --git a/Tests/Functional/Entity/SymfonyConstraints.php b/Tests/Functional/Entity/SymfonyConstraints.php index 7a601a316..0218153fb 100644 --- a/Tests/Functional/Entity/SymfonyConstraints.php +++ b/Tests/Functional/Entity/SymfonyConstraints.php @@ -11,11 +11,11 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Validator\Constraints as Assert; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { class SymfonyConstraints { /** diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php index f0131e119..1d5e177b2 100644 --- a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php @@ -11,13 +11,12 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { class SymfonyConstraintsWithValidationGroups { /** @@ -67,7 +66,7 @@ class SymfonyConstraintsWithValidationGroups /** * @var array */ - #[OAT\Property(type: 'array', items: new OAT\Items(type: 'string'))] + #[\OpenApi\Attributes\Property(type: 'array', items: new \OpenApi\Attributes\Items(type: 'string'))] #[Assert\Valid] public $propertyArray; } diff --git a/Tests/Functional/Entity/SymfonyDiscriminator.php b/Tests/Functional/Entity/SymfonyDiscriminator.php index 4341b6159..ea9a2258d 100644 --- a/Tests/Functional/Entity/SymfonyDiscriminator.php +++ b/Tests/Functional/Entity/SymfonyDiscriminator.php @@ -11,10 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use Symfony\Component\HttpKernel\Kernel; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Serializer\Annotation\DiscriminatorMap; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @DiscriminatorMap(typeProperty="type", mapping={ * "one": SymfonyDiscriminatorOne::class, diff --git a/Tests/Functional/Entity/User.php b/Tests/Functional/Entity/User.php index b06f7f545..f5c21094c 100644 --- a/Tests/Functional/Entity/User.php +++ b/Tests/Functional/Entity/User.php @@ -11,11 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; -use OpenApi\Attributes as OAT; -use Symfony\Component\HttpKernel\Kernel; -if (Kernel::MAJOR_VERSION < 7) { +if (TestKernel::isAnnotationsAvailable()) { /** * @author Guilhem N. */ @@ -180,10 +179,10 @@ class User /** * @var int */ - #[OAT\Property(description: 'User id', readOnly: true, title: 'userid', default: null)] + #[\OpenApi\Attributes\Property(description: 'User id', readOnly: true, title: 'userid', default: null)] private $id; - #[OAT\Property(type: 'string', readOnly: false)] + #[\OpenApi\Attributes\Property(type: 'string', readOnly: false)] private $email; /** @@ -191,31 +190,31 @@ class User * * @var string[] */ - #[OAT\Property(description: 'User roles', title: 'roles', example: '["ADMIN","SUPERUSER"]', default: ['user'])] + #[\OpenApi\Attributes\Property(description: 'User roles', title: 'roles', example: '["ADMIN","SUPERUSER"]', default: ['user'])] private $roles; /** * User Location. */ - #[OAT\Property(type: 'string')] + #[\OpenApi\Attributes\Property(type: 'string')] private $location; /** * @var int */ - #[OAT\Property(type: 'string')] + #[\OpenApi\Attributes\Property(type: 'string')] private $friendsNumber; /** * @var float */ - #[OAT\Property(default: 0.0)] + #[\OpenApi\Attributes\Property(default: 0.0)] private $money; /** * @var \DateTime */ - #[OAT\Property(property: 'creationDate')] + #[\OpenApi\Attributes\Property(property: 'creationDate')] private $createdAt; /** @@ -236,7 +235,7 @@ class User /** * @var string */ - #[OAT\Property(enum: ['disabled', 'enabled'])] + #[\OpenApi\Attributes\Property(enum: ['disabled', 'enabled'])] private $status; /** @@ -249,7 +248,7 @@ public function setMoney(float $money) $this->money = $money; } - #[OAT\Property(example: 1)] + #[\OpenApi\Attributes\Property(example: 1)] public function setId(int $id) { $this->id = $id; From 365b371ebb7c1a27e1096f573061e6cdafab5761 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 02:21:00 +0100 Subject: [PATCH 38/54] Revert "test: check if reader available" This reverts commit 67ad8877076f751210d565c5cba75c07094d3f00. --- Tests/Functional/BazingaFunctionalTest.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Tests/Functional/BazingaFunctionalTest.php b/Tests/Functional/BazingaFunctionalTest.php index d1b1beec1..92df0d95a 100644 --- a/Tests/Functional/BazingaFunctionalTest.php +++ b/Tests/Functional/BazingaFunctionalTest.php @@ -19,15 +19,13 @@ class BazingaFunctionalTest extends WebTestCase { protected function setUp(): void { + if (Kernel::MAJOR_VERSION >= 7) { + $this->markTestSkipped('Not supported in symfony 7'); + } + parent::setUp(); static::createClient([], ['HTTP_HOST' => 'api.example.com']); - - try { - self::getContainer()->get('annotations.reader'); - } catch (\Throwable $e) { - $this->markTestSkipped('Hateoas requires doctrine/annotations'); - } } public function testModelComplexDocumentationBazinga() From 2a37f0181242b3c4232199158152546f68792c1b Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 02:29:55 +0100 Subject: [PATCH 39/54] fix: SymfonyConstraintsWithValidationGroups --- ...SymfonyConstraintsWithValidationGroups.php | 53 +------------------ ...mfonyConstraintsWithValidationGroups80.php | 46 ++++++++++++++++ ...mfonyConstraintsWithValidationGroups81.php | 40 ++++++++++++++ 3 files changed, 88 insertions(+), 51 deletions(-) create mode 100644 Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups80.php create mode 100644 Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups81.php diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php index 1d5e177b2..d73431b25 100644 --- a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups.php @@ -12,62 +12,13 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; -use OpenApi\Annotations as OA; -use Symfony\Component\Serializer\Annotation\Groups; -use Symfony\Component\Validator\Constraints as Assert; if (TestKernel::isAnnotationsAvailable()) { - class SymfonyConstraintsWithValidationGroups + class SymfonyConstraintsWithValidationGroups extends SymfonyConstraintsWithValidationGroups80 { - /** - * @var int - * - * @Groups("test") - * - * @Assert\NotBlank(groups={"test"}) - * - * @Assert\Range(min=1, max=100) - */ - public $property; - - /** - * @var int - * - * @Assert\Range(min=1, max=100) - */ - public $propertyInDefaultGroup; - - /** - * @var array - * - * @OA\Property(type="array", @OA\Items(type="string")) - * - * @Assert\Valid - */ - public $propertyArray; } } else { - class SymfonyConstraintsWithValidationGroups + class SymfonyConstraintsWithValidationGroups extends SymfonyConstraintsWithValidationGroups81 { - /** - * @var int - */ - #[Assert\Range(min: 1, max: 100)] - #[Assert\NotBlank(groups: ['test'])] - #[Groups('test')] - public $property; - - /** - * @var int - */ - #[Assert\Range(min: 1, max: 100)] - public $propertyInDefaultGroup; - - /** - * @var array - */ - #[\OpenApi\Attributes\Property(type: 'array', items: new \OpenApi\Attributes\Items(type: 'string'))] - #[Assert\Valid] - public $propertyArray; } } diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups80.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups80.php new file mode 100644 index 000000000..c03794602 --- /dev/null +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups80.php @@ -0,0 +1,46 @@ + Date: Sun, 17 Dec 2023 02:56:54 +0100 Subject: [PATCH 40/54] test: fix routes available for both annotations & attributes --- Tests/Functional/Controller/ApiController.php | 73 +++++++++++++++++-- .../Controller/FOSRestController.php | 34 +++++++-- Tests/Functional/TestKernel.php | 5 ++ 3 files changed, 102 insertions(+), 10 deletions(-) diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index c3488723a..7bd358ea9 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -11,15 +11,78 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; +use Nelmio\ApiDocBundle\Annotation\Areas; +use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Annotation\Security; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; if (TestKernel::isAnnotationsAvailable()) { - /** - * @Route("/api", name="api_", host="api.example.com") - */ - class ApiController extends ApiController80 - { + if (TestKernel::isAttributesAvailable()) { + #[Route('/api', name: 'api_', host: 'api.example.com')] + class ApiController extends ApiController80 + { + #[\OpenApi\Attributes\Get(responses: [ + new \OpenApi\Attributes\Response( + response: '200', + description: 'Success', + attachables: [ + new Model(type: Article::class, groups: ['light']), + ], + ), + ])] + #[\OpenApi\Attributes\Parameter(ref: '#/components/parameters/test')] + #[Route('/article_attributes/{id}', methods: ['GET'])] + #[\OpenApi\Attributes\Parameter(name: 'Accept-Version', in: 'header', schema: new \OpenApi\Attributes\Schema(type: 'string'))] + public function fetchArticleActionWithAttributes() + { + } + + #[Areas(['area', 'area2'])] + #[Route('/areas_attributes/new', methods: ['GET', 'POST'])] + public function newAreaActionAttributes() + { + } + + #[Route('/security_attributes')] + #[\OpenApi\Attributes\Response(response: '201', description: '')] + #[Security(name: 'api_key')] + #[Security(name: 'basic')] + #[Security(name: 'oauth2', scopes: ['scope_1'])] + public function securityActionAttributes() + { + } + + #[Route('/security_override_attributes')] + #[\OpenApi\Attributes\Response(response: '201', description: '')] + #[Security(name: 'api_key')] + #[Security(name: null)] + public function securityOverrideActionAttributes() + { + } + + #[Route('/inline_path_parameters')] + #[\OpenApi\Attributes\Response(response: '200', description: '')] + public function inlinePathParameters( + #[\OpenApi\Attributes\PathParameter] string $product_id + ) { + } + + #[Route('/enum')] + #[\OpenApi\Attributes\Response(response: '201', description: '', attachables: [new Model(type: Article81::class)])] + public function enum() + { + } + } + } else { + /** + * @Route("/api", name="api_", host="api.example.com") + */ + class ApiController extends ApiController80 + { + } } } else { #[Route('/api', name: 'api_', host: 'api.example.com')] diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index fb0401622..adf54e675 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -11,15 +11,39 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; +use FOS\RestBundle\Controller\Annotations\QueryParam; +use FOS\RestBundle\Controller\Annotations\RequestParam; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Validator\Constraints\DateTime; +use Symfony\Component\Validator\Constraints\IsTrue; +use Symfony\Component\Validator\Constraints\Regex; if (TestKernel::isAnnotationsAvailable()) { - /** - * @Route("/api", host="api.example.com") - */ - class FOSRestController extends FOSRestController80 - { + if (TestKernel::isAttributesAvailable()) { + #[Route("/api", host: "api.example.com")] + class FOSRestController extends FOSRestController80 + { + #[Route('/fosrest_attributes.{_format}', methods: ['POST'])] + #[QueryParam(name: 'foo', requirements: new Regex('/^\d+$/'))] + #[QueryParam(name: 'mapped', map: true)] + #[RequestParam(name: 'Barraa', key: 'bar', requirements: '\d+')] + #[RequestParam(name: 'baz', requirements: new IsTrue())] + #[RequestParam(name: 'datetime', requirements: new DateTime('Y-m-d\TH:i:sP'))] + #[RequestParam(name: 'datetimeAlt', requirements: new DateTime('c'))] + #[RequestParam(name: 'datetimeNoFormat', requirements: new DateTime())] + #[RequestParam(name: 'date', requirements: new DateTime('Y-m-d'))] + public function fosrestAttributesAction() + { + } + } + } else { + /** + * @Route("/api", host="api.example.com") + */ + class FOSRestController extends FOSRestController80 + { + } } } else { #[Route("/api", host: "api.example.com")] diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 54cb11aef..5224272f4 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -350,4 +350,9 @@ public static function isAnnotationsAvailable(): bool return PHP_VERSION_ID < 80100; } + + public static function isAttributesAvailable(): bool + { + return PHP_VERSION_ID >= 80100; + } } From 10ac4290874bde4dde0a216041c9644b7eb936b2 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 02:57:14 +0100 Subject: [PATCH 41/54] test: fix routes available for both annotations & attributes --- Tests/Functional/FunctionalTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index 58ebe2c28..e294f8246 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -17,7 +17,6 @@ use OpenApi\Annotations as OAAnnotations; use OpenApi\Attributes as OAAttributes; use OpenApi\Generator; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Serializer\Annotation\SerializedName; class FunctionalTest extends WebTestCase From b304c0a6b8476a22c978ef850348a8fcd89435c9 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 12:43:40 +0100 Subject: [PATCH 42/54] fix: ci php 8.0 --- Tests/Functional/Controller/ApiController.php | 79 +------ .../Functional/Controller/ApiController80.php | 4 +- .../Functional/Controller/ApiController81.php | 4 +- .../Controller/FOSRestController.php | 40 +--- .../Controller/FOSRestController81.php | 15 +- .../Functional/Controller/JMSController80.php | 4 +- .../Functional/Controller/JMSController81.php | 4 +- .../Entity/EntityWithAlternateType.php | 53 ----- .../Entity/EntityWithAlternateType80.php | 34 +++ .../Entity/EntityWithAlternateType81.php | 32 +++ Tests/Functional/Entity/JMSComplex.php | 46 ---- Tests/Functional/Entity/JMSComplex80.php | 9 + Tests/Functional/Entity/JMSComplex81.php | 10 + Tests/Functional/Entity/JMSDualComplex80.php | 2 +- Tests/Functional/Entity/JMSDualComplex81.php | 2 +- .../Entity/SymfonyConstraints80.php | 200 ++++++++++++++++++ .../Entity/SymfonyConstraints81.php | 184 ++++++++++++++++ .../Entity/SymfonyDiscriminator80.php | 28 +++ .../Entity/SymfonyDiscriminator81.php | 26 +++ Tests/Functional/FOSRestTest.php | 2 +- Tests/Functional/FunctionalTest.php | 12 +- Tests/Functional/TestKernel.php | 6 +- 22 files changed, 575 insertions(+), 221 deletions(-) delete mode 100644 Tests/Functional/Entity/EntityWithAlternateType.php create mode 100644 Tests/Functional/Entity/EntityWithAlternateType80.php create mode 100644 Tests/Functional/Entity/EntityWithAlternateType81.php delete mode 100644 Tests/Functional/Entity/JMSComplex.php create mode 100644 Tests/Functional/Entity/SymfonyConstraints80.php create mode 100644 Tests/Functional/Entity/SymfonyConstraints81.php create mode 100644 Tests/Functional/Entity/SymfonyDiscriminator80.php create mode 100644 Tests/Functional/Entity/SymfonyDiscriminator81.php diff --git a/Tests/Functional/Controller/ApiController.php b/Tests/Functional/Controller/ApiController.php index 7bd358ea9..1467a8695 100644 --- a/Tests/Functional/Controller/ApiController.php +++ b/Tests/Functional/Controller/ApiController.php @@ -11,82 +11,19 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Areas; -use Nelmio\ApiDocBundle\Annotation\Model; -use Nelmio\ApiDocBundle\Annotation\Security; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; -if (TestKernel::isAnnotationsAvailable()) { - if (TestKernel::isAttributesAvailable()) { - #[Route('/api', name: 'api_', host: 'api.example.com')] - class ApiController extends ApiController80 - { - #[\OpenApi\Attributes\Get(responses: [ - new \OpenApi\Attributes\Response( - response: '200', - description: 'Success', - attachables: [ - new Model(type: Article::class, groups: ['light']), - ], - ), - ])] - #[\OpenApi\Attributes\Parameter(ref: '#/components/parameters/test')] - #[Route('/article_attributes/{id}', methods: ['GET'])] - #[\OpenApi\Attributes\Parameter(name: 'Accept-Version', in: 'header', schema: new \OpenApi\Attributes\Schema(type: 'string'))] - public function fetchArticleActionWithAttributes() - { - } - - #[Areas(['area', 'area2'])] - #[Route('/areas_attributes/new', methods: ['GET', 'POST'])] - public function newAreaActionAttributes() - { - } - - #[Route('/security_attributes')] - #[\OpenApi\Attributes\Response(response: '201', description: '')] - #[Security(name: 'api_key')] - #[Security(name: 'basic')] - #[Security(name: 'oauth2', scopes: ['scope_1'])] - public function securityActionAttributes() - { - } - - #[Route('/security_override_attributes')] - #[\OpenApi\Attributes\Response(response: '201', description: '')] - #[Security(name: 'api_key')] - #[Security(name: null)] - public function securityOverrideActionAttributes() - { - } - - #[Route('/inline_path_parameters')] - #[\OpenApi\Attributes\Response(response: '200', description: '')] - public function inlinePathParameters( - #[\OpenApi\Attributes\PathParameter] string $product_id - ) { - } - - #[Route('/enum')] - #[\OpenApi\Attributes\Response(response: '201', description: '', attachables: [new Model(type: Article81::class)])] - public function enum() - { - } - } - } else { - /** - * @Route("/api", name="api_", host="api.example.com") - */ - class ApiController extends ApiController80 - { - } - } -} else { +if (TestKernel::isAttributesAvailable()) { #[Route('/api', name: 'api_', host: 'api.example.com')] class ApiController extends ApiController81 { } +} else { + /** + * @Route("/api", name="api_", host="api.example.com") + */ + class ApiController extends ApiController80 + { + } } diff --git a/Tests/Functional/Controller/ApiController80.php b/Tests/Functional/Controller/ApiController80.php index 6f5187dc2..5d92d0717 100644 --- a/Tests/Functional/Controller/ApiController80.php +++ b/Tests/Functional/Controller/ApiController80.php @@ -18,7 +18,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArticleInterface; use Nelmio\ApiDocBundle\Tests\Functional\Entity\CompoundEntity; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType80; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithNullableSchemaSet; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithObjectType; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; @@ -374,7 +374,7 @@ public function symfonyConstraintsWithGroupsAction() * @OA\Get(operationId="alternate-entity-type") * * @OA\Response(response=200, description="success", @OA\JsonContent( - * ref=@Model(type=EntityWithAlternateType::class), + * ref=@Model(type=EntityWithAlternateType80::class), * )) */ public function alternateEntityType() diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index 6fbe86092..1e7d302ed 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -22,7 +22,7 @@ use Nelmio\ApiDocBundle\Annotation\Operation; use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArticleInterface; use Nelmio\ApiDocBundle\Tests\Functional\Entity\CompoundEntity; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithNullableSchemaSet; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithObjectType; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; @@ -296,7 +296,7 @@ public function symfonyConstraintsWithGroupsAction() response: 200, description: 'success', content: new OA\JsonContent( - ref: new Model(type: EntityWithAlternateType::class), + ref: new Model(type: EntityWithAlternateType81::class), ), )] public function alternateEntityType() diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index adf54e675..066a4dce8 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -11,43 +11,19 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use FOS\RestBundle\Controller\Annotations\QueryParam; -use FOS\RestBundle\Controller\Annotations\RequestParam; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Symfony\Component\Routing\Annotation\Route; -use Symfony\Component\Validator\Constraints\DateTime; -use Symfony\Component\Validator\Constraints\IsTrue; -use Symfony\Component\Validator\Constraints\Regex; -if (TestKernel::isAnnotationsAvailable()) { - if (TestKernel::isAttributesAvailable()) { - #[Route("/api", host: "api.example.com")] - class FOSRestController extends FOSRestController80 - { - #[Route('/fosrest_attributes.{_format}', methods: ['POST'])] - #[QueryParam(name: 'foo', requirements: new Regex('/^\d+$/'))] - #[QueryParam(name: 'mapped', map: true)] - #[RequestParam(name: 'Barraa', key: 'bar', requirements: '\d+')] - #[RequestParam(name: 'baz', requirements: new IsTrue())] - #[RequestParam(name: 'datetime', requirements: new DateTime('Y-m-d\TH:i:sP'))] - #[RequestParam(name: 'datetimeAlt', requirements: new DateTime('c'))] - #[RequestParam(name: 'datetimeNoFormat', requirements: new DateTime())] - #[RequestParam(name: 'date', requirements: new DateTime('Y-m-d'))] - public function fosrestAttributesAction() - { - } - } - } else { - /** - * @Route("/api", host="api.example.com") - */ - class FOSRestController extends FOSRestController80 - { - } - } -} else { +if (TestKernel::isAttributesAvailable()) { #[Route("/api", host: "api.example.com")] class FOSRestController extends FOSRestController81 { } +} else { + /** + * @Route("/api", host="api.example.com") + */ + class FOSRestController extends FOSRestController80 + { + } } diff --git a/Tests/Functional/Controller/FOSRestController81.php b/Tests/Functional/Controller/FOSRestController81.php index d822d7ccc..f74c09ec2 100644 --- a/Tests/Functional/Controller/FOSRestController81.php +++ b/Tests/Functional/Controller/FOSRestController81.php @@ -18,8 +18,21 @@ use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Regex; -class FOSRestController81 extends FOSRestController80 +class FOSRestController81 { + #[Route('/fosrest.{_format}', methods: ['POST'])] + #[QueryParam(name: 'foo', requirements: new Regex('/^\d+$/'))] + #[QueryParam(name: 'mapped', map: true)] + #[RequestParam(name: 'Barraa', key: 'bar', requirements: '\d+')] + #[RequestParam(name: 'baz', requirements: new IsTrue())] + #[RequestParam(name: 'datetime', requirements: new DateTime('Y-m-d\TH:i:sP'))] + #[RequestParam(name: 'datetimeAlt', requirements: new DateTime('c'))] + #[RequestParam(name: 'datetimeNoFormat', requirements: new DateTime())] + #[RequestParam(name: 'date', requirements: new DateTime('Y-m-d'))] + public function fosrestAction() + { + } + #[Route('/fosrest_attributes.{_format}', methods: ['POST'])] #[QueryParam(name: 'foo', requirements: new Regex('/^\d+$/'))] #[QueryParam(name: 'mapped', map: true)] diff --git a/Tests/Functional/Controller/JMSController80.php b/Tests/Functional/Controller/JMSController80.php index e7f42d49b..53ca9c2b3 100644 --- a/Tests/Functional/Controller/JMSController80.php +++ b/Tests/Functional/Controller/JMSController80.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use Nelmio\ApiDocBundle\Annotation\Model; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex80; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSDualComplex; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNamingStrategyConstraints; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser; @@ -61,7 +61,7 @@ public function yamlAction() * response=200, * description="Success", * - * @Model(type=JMSComplex::class, groups={"list", "details", "User" : {"list"}}) + * @Model(type=JMSComplex80::class, groups={"list", "details", "User" : {"list"}}) * ) */ public function complexAction() diff --git a/Tests/Functional/Controller/JMSController81.php b/Tests/Functional/Controller/JMSController81.php index 7101a4381..529eedf24 100644 --- a/Tests/Functional/Controller/JMSController81.php +++ b/Tests/Functional/Controller/JMSController81.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use Nelmio\ApiDocBundle\Annotation\Model; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSDualComplex; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSNamingStrategyConstraints; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser; @@ -51,7 +51,7 @@ public function yamlAction() response: 200, description: "Success", content: new Model( - type: JMSComplex::class, + type: JMSComplex81::class, groups: ["list", "details", "User" => ["list"]]) )] public function complexAction() diff --git a/Tests/Functional/Entity/EntityWithAlternateType.php b/Tests/Functional/Entity/EntityWithAlternateType.php deleted file mode 100644 index cab6fdc03..000000000 --- a/Tests/Functional/Entity/EntityWithAlternateType.php +++ /dev/null @@ -1,53 +0,0 @@ -propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; + } + + /** + * @Assert\Count(min="0", max="10") + */ + public function setPropertyNotBlank(int $propertyNotBlank): void + { + $this->propertyNotBlank = $propertyNotBlank; + } + + public function setPropertyNotNull(int $propertyNotNull): void + { + $this->propertyNotNull = $propertyNotNull; + } + + public function setPropertyAssertLength(int $propertyAssertLength): void + { + $this->propertyAssertLength = $propertyAssertLength; + } + + public function setPropertyRegex(int $propertyRegex): void + { + $this->propertyRegex = $propertyRegex; + } + + public function setPropertyCount(int $propertyCount): void + { + $this->propertyCount = $propertyCount; + } + + public function setPropertyChoice(int $propertyChoice): void + { + $this->propertyChoice = $propertyChoice; + } + + public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void + { + $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; + } + + public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void + { + $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; + } + + public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void + { + $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; + } + + public function setPropertyExpression(int $propertyExpression): void + { + $this->propertyExpression = $propertyExpression; + } + + public function setPropertyRange(int $propertyRange): void + { + $this->propertyRange = $propertyRange; + } + + public function setPropertyLessThan(int $propertyLessThan): void + { + $this->propertyLessThan = $propertyLessThan; + } + + public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void + { + $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; + } + + /** + * @return array + */ + public static function fetchAllowedChoices() + { + return ['choice1', 'choice2']; + } +} \ No newline at end of file diff --git a/Tests/Functional/Entity/SymfonyConstraints81.php b/Tests/Functional/Entity/SymfonyConstraints81.php new file mode 100644 index 000000000..c21d4e318 --- /dev/null +++ b/Tests/Functional/Entity/SymfonyConstraints81.php @@ -0,0 +1,184 @@ +propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; + } + + #[Assert\Count(min: '0', max: '10')] + public function setPropertyNotBlank(int $propertyNotBlank): void + { + $this->propertyNotBlank = $propertyNotBlank; + } + + public function setPropertyNotNull(int $propertyNotNull): void + { + $this->propertyNotNull = $propertyNotNull; + } + + public function setPropertyAssertLength(int $propertyAssertLength): void + { + $this->propertyAssertLength = $propertyAssertLength; + } + + public function setPropertyRegex(int $propertyRegex): void + { + $this->propertyRegex = $propertyRegex; + } + + public function setPropertyCount(int $propertyCount): void + { + $this->propertyCount = $propertyCount; + } + + public function setPropertyChoice(int $propertyChoice): void + { + $this->propertyChoice = $propertyChoice; + } + + public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void + { + $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; + } + + public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void + { + $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; + } + + public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void + { + $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; + } + + public function setPropertyExpression(int $propertyExpression): void + { + $this->propertyExpression = $propertyExpression; + } + + public function setPropertyRange(int $propertyRange): void + { + $this->propertyRange = $propertyRange; + } + + public function setPropertyLessThan(int $propertyLessThan): void + { + $this->propertyLessThan = $propertyLessThan; + } + + public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void + { + $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; + } + + /** + * @return array + */ + public static function fetchAllowedChoices() + { + return ['choice1', 'choice2']; + } +} \ No newline at end of file diff --git a/Tests/Functional/Entity/SymfonyDiscriminator80.php b/Tests/Functional/Entity/SymfonyDiscriminator80.php new file mode 100644 index 000000000..5ce246571 --- /dev/null +++ b/Tests/Functional/Entity/SymfonyDiscriminator80.php @@ -0,0 +1,28 @@ + SymfonyDiscriminatorOne::class, 'two' => SymfonyDiscriminatorTwo::class] +)] +abstract class SymfonyDiscriminator81 +{ + /** + * @var string + */ + public $type; +} \ No newline at end of file diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index c915cf44a..6ccbfa880 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -85,7 +85,7 @@ public function provideRoute(): iterable { yield 'Annotations' => ['/api/fosrest']; - if (\PHP_VERSION_ID >= 80100) { + if (TestKernel::isAttributesAvailable()) { yield 'Attributes' => ['/api/fosrest_attributes']; } } diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index e294f8246..e36275f61 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -543,10 +543,10 @@ public function testSerializedNameAction() $this->markTestSkipped('Annotation @SerializedName doesn\'t exist.'); } - if (TestKernel::isAnnotationsAvailable()) { - $model = $this->getModel('SerializedNameEnt'); - } else { + if (TestKernel::isAttributesAvailable()) { $model = $this->getModel('SerializedNameEntity'); + } else { + $model = $this->getModel('SerializedNameEnt'); } $this->assertCount(2, $model->properties); @@ -671,7 +671,11 @@ public function testEnumSupport() public function testEntitiesWithOverriddenSchemaTypeDoNotReadOtherProperties() { - $model = $this->getModel('EntityWithAlternateType'); + if (TestKernel::isAttributesAvailable()) { + $model = $this->getModel('EntityWithAlternateType81'); + } else { + $model = $this->getModel('EntityWithAlternateType80'); + } $this->assertSame('array', $model->type); $this->assertSame('string', $model->items->type); diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 5224272f4..99e28208f 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -19,7 +19,7 @@ use JMS\SerializerBundle\JMSSerializerBundle; use Nelmio\ApiDocBundle\NelmioApiDocBundle; use Nelmio\ApiDocBundle\Tests\Functional\Entity\BazingaUser; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex80; use Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSPicture; use Nelmio\ApiDocBundle\Tests\Functional\Entity\PrivateProtectedExposure; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; @@ -287,7 +287,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], [ 'alias' => 'JMSComplex', - 'type' => JMSComplex::class, + 'type' => JMSComplex80::class, 'groups' => [ 'list', 'details', @@ -296,7 +296,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], [ 'alias' => 'JMSComplexDefault', - 'type' => JMSComplex::class, + 'type' => JMSComplex80::class, 'groups' => null, ], [ From a043b1ffc01e5ccb0b0c76a2b756529e6dd92683 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Sun, 17 Dec 2023 12:52:31 +0100 Subject: [PATCH 43/54] fix: aliasing JMSComplex81 --- Tests/Functional/TestKernel.php | 102 +++++++++++++++++++------------- 1 file changed, 62 insertions(+), 40 deletions(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 99e28208f..87c8392fb 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -198,6 +198,67 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load } } + $models = [ + [ + 'alias' => 'PrivateProtectedExposure', + 'type' => PrivateProtectedExposure::class, + ], + [ + 'alias' => 'JMSPicture_mini', + 'type' => JMSPicture::class, + 'groups' => ['mini'], + ], + [ + 'alias' => 'BazingaUser_grouped', + 'type' => BazingaUser::class, + 'groups' => ['foo'], + ], + [ + 'alias' => 'JMSComplex', + 'type' => JMSComplex80::class, + 'groups' => [ + 'list', + 'details', + 'User' => ['list'], + ], + ], + [ + 'alias' => 'JMSComplexDefault', + 'type' => JMSComplex80::class, + 'groups' => null, + ], + [ + 'alias' => 'SymfonyConstraintsTestGroup', + 'type' => SymfonyConstraintsWithValidationGroups::class, + 'groups' => ['test'], + ], + [ + 'alias' => 'SymfonyConstraintsDefaultGroup', + 'type' => SymfonyConstraintsWithValidationGroups::class, + 'groups' => null, + ], + ]; + + if (self::isAttributesAvailable()) { + $models = [ + ...$models, + [ + 'alias' => 'JMSComplex', + 'type' => \Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81::class, + 'groups' => [ + 'list', + 'details', + 'User' => ['list'], + ], + ], + [ + 'alias' => 'JMSComplexDefault', + 'type' => \Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81::class, + 'groups' => null, + ] + ]; + } + // Filter routes $c->loadFromExtension('nelmio_api_doc', [ 'use_validation_groups' => boolval($this->flags & self::USE_VALIDATION_GROUPS), @@ -270,46 +331,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], ], 'models' => [ - 'names' => [ - [ - 'alias' => 'PrivateProtectedExposure', - 'type' => PrivateProtectedExposure::class, - ], - [ - 'alias' => 'JMSPicture_mini', - 'type' => JMSPicture::class, - 'groups' => ['mini'], - ], - [ - 'alias' => 'BazingaUser_grouped', - 'type' => BazingaUser::class, - 'groups' => ['foo'], - ], - [ - 'alias' => 'JMSComplex', - 'type' => JMSComplex80::class, - 'groups' => [ - 'list', - 'details', - 'User' => ['list'], - ], - ], - [ - 'alias' => 'JMSComplexDefault', - 'type' => JMSComplex80::class, - 'groups' => null, - ], - [ - 'alias' => 'SymfonyConstraintsTestGroup', - 'type' => SymfonyConstraintsWithValidationGroups::class, - 'groups' => ['test'], - ], - [ - 'alias' => 'SymfonyConstraintsDefaultGroup', - 'type' => SymfonyConstraintsWithValidationGroups::class, - 'groups' => null, - ], - ], + 'names' => $models, ], ]); From aac792e7ce1b4021a2b01db130e7d112e0b5e4bc Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 15:59:00 +0100 Subject: [PATCH 44/54] test: fix mapping not being set --- Tests/Functional/TestKernel.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 87c8392fb..498b883b5 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -126,19 +126,25 @@ private function import($routes, $resource, $prefix, $type) protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) { + $framework = [ 'assets' => true, 'secret' => 'MySecretKey', 'test' => null, 'validation' => null, 'form' => null, - 'serializer' => PHP_VERSION_ID >= 80100 && Kernel::MAJOR_VERSION < 7 ? ['enable_annotations' => true] : [] + [ + 'serializer' => ( + PHP_VERSION_ID >= 80100 && Kernel::MAJOR_VERSION < 7 + ? ['enable_annotations' => true] + : [] + ) + [ 'mapping' => [ 'paths' => [__DIR__.'/Resources/serializer/'], ], ], 'property_access' => true, ]; + // Support symfony/framework-bundle < 5.4 if (method_exists(\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand::class, 'complete')) { $framework += [ From b79fca879c32f2341f832602cf634c746fc1e74b Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:05:15 +0100 Subject: [PATCH 45/54] test: use array_merge --- Tests/Functional/TestKernel.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 498b883b5..fadcdf6c0 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -246,8 +246,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ]; if (self::isAttributesAvailable()) { - $models = [ - ...$models, + $models = array_merge($models, [ [ 'alias' => 'JMSComplex', 'type' => \Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81::class, @@ -256,13 +255,13 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'details', 'User' => ['list'], ], - ], - [ - 'alias' => 'JMSComplexDefault', - 'type' => \Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81::class, - 'groups' => null, - ] - ]; + ], + [ + 'alias' => 'JMSComplexDefault', + 'type' => \Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81::class, + 'groups' => null, + ] + ]); } // Filter routes From b73782424a4e9e6c825dac8a878621d808c8e358 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:09:42 +0100 Subject: [PATCH 46/54] test: fix php 8.1 duplicate aliases set --- Tests/Functional/TestKernel.php | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index fadcdf6c0..17a47d3f9 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -219,20 +219,6 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'type' => BazingaUser::class, 'groups' => ['foo'], ], - [ - 'alias' => 'JMSComplex', - 'type' => JMSComplex80::class, - 'groups' => [ - 'list', - 'details', - 'User' => ['list'], - ], - ], - [ - 'alias' => 'JMSComplexDefault', - 'type' => JMSComplex80::class, - 'groups' => null, - ], [ 'alias' => 'SymfonyConstraintsTestGroup', 'type' => SymfonyConstraintsWithValidationGroups::class, @@ -245,7 +231,24 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ], ]; - if (self::isAttributesAvailable()) { + if (self::isAnnotationsAvailable()) { + $models = array_merge($models, [ + [ + 'alias' => 'JMSComplex', + 'type' => JMSComplex80::class, + 'groups' => [ + 'list', + 'details', + 'User' => ['list'], + ], + ], + [ + 'alias' => 'JMSComplexDefault', + 'type' => JMSComplex80::class, + 'groups' => null, + ], + ]); + } elseif (self::isAttributesAvailable()) { $models = array_merge($models, [ [ 'alias' => 'JMSComplex', From 7b256d66c0d26ddf07c8fd32c8adc15cdb88fe3c Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:13:43 +0100 Subject: [PATCH 47/54] temp: remove fail-fast from ci --- .github/workflows/continuous-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index d73a2395c..2165a7e6e 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -14,7 +14,7 @@ on: - master env: - fail-fast: true + fail-fast: false jobs: phpunit: From 6fc587698259c2b7b06a6736fdb3b2833f657002 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:36:49 +0100 Subject: [PATCH 48/54] test: fix php 7 extend from SymfonyConstraints81 --- .../Functional/Entity/SymfonyConstraints.php | 167 +-------------- .../Entity/SymfonyConstraints80.php | 200 ------------------ 2 files changed, 1 insertion(+), 366 deletions(-) delete mode 100644 Tests/Functional/Entity/SymfonyConstraints80.php diff --git a/Tests/Functional/Entity/SymfonyConstraints.php b/Tests/Functional/Entity/SymfonyConstraints.php index 0218153fb..451fc2830 100644 --- a/Tests/Functional/Entity/SymfonyConstraints.php +++ b/Tests/Functional/Entity/SymfonyConstraints.php @@ -201,172 +201,7 @@ public static function fetchAllowedChoices() } } } else { - class SymfonyConstraints + class SymfonyConstraints extends SymfonyConstraints81 { - /** - * @var int - */ - #[Assert\NotBlank(groups: ['test'])] - private $propertyNotBlank; - - /** - * @var int - */ - #[Assert\NotNull()] - private $propertyNotNull; - - /** - * @var int - */ - #[Assert\Length(min: '0', max: '50')] - private $propertyAssertLength; - - /** - * @var int - */ - #[Assert\Regex(pattern: '/[a-z]{2}/')] - private $propertyRegex; - - /** - * @var int - */ - #[Assert\Count(min: '0', max: '10')] - private $propertyCount; - - /** - * @var int - */ - #[Assert\Choice(choices: ['choice1', 'choice2'])] - private $propertyChoice; - - /** - * @var int - */ - #[Assert\Choice(callback: [self::class, 'fetchAllowedChoices'])] - private $propertyChoiceWithCallback; - - /** - * @var int - */ - #[Assert\Choice(callback: 'fetchAllowedChoices')] - private $propertyChoiceWithCallbackWithoutClass; - - /** - * @var string[] - */ - #[Assert\Choice(multiple: true, choices: ['choice1', 'choice2'])] - private $propertyChoiceWithMultiple; - - /** - * @var int - */ - #[Assert\Expression( - "this.getCategory() in ['php', 'symfony'] or !this.isTechnicalPost()", - message: 'If this is a tech post, the category should be either php or symfony!' - )] - private $propertyExpression; - - /** - * @var int - */ - #[Assert\Range(min: 1, max: 5)] - private $propertyRange; - - /** - * @var int - */ - #[Assert\LessThan(42)] - private $propertyLessThan; - - /** - * @var int - */ - #[Assert\LessThanOrEqual(23)] - private $propertyLessThanOrEqual; - - /** - * @var int - */ - #[CustomAssert\CompoundValidationRule] - private $propertyWithCompoundValidationRule; - - public function setPropertyWithCompoundValidationRule(int $propertyWithCompoundValidationRule): void - { - $this->propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; - } - - #[Assert\Count(min: '0', max: '10')] - public function setPropertyNotBlank(int $propertyNotBlank): void - { - $this->propertyNotBlank = $propertyNotBlank; - } - - public function setPropertyNotNull(int $propertyNotNull): void - { - $this->propertyNotNull = $propertyNotNull; - } - - public function setPropertyAssertLength(int $propertyAssertLength): void - { - $this->propertyAssertLength = $propertyAssertLength; - } - - public function setPropertyRegex(int $propertyRegex): void - { - $this->propertyRegex = $propertyRegex; - } - - public function setPropertyCount(int $propertyCount): void - { - $this->propertyCount = $propertyCount; - } - - public function setPropertyChoice(int $propertyChoice): void - { - $this->propertyChoice = $propertyChoice; - } - - public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void - { - $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; - } - - public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void - { - $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; - } - - public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void - { - $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; - } - - public function setPropertyExpression(int $propertyExpression): void - { - $this->propertyExpression = $propertyExpression; - } - - public function setPropertyRange(int $propertyRange): void - { - $this->propertyRange = $propertyRange; - } - - public function setPropertyLessThan(int $propertyLessThan): void - { - $this->propertyLessThan = $propertyLessThan; - } - - public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void - { - $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; - } - - /** - * @return array - */ - public static function fetchAllowedChoices() - { - return ['choice1', 'choice2']; - } } } diff --git a/Tests/Functional/Entity/SymfonyConstraints80.php b/Tests/Functional/Entity/SymfonyConstraints80.php deleted file mode 100644 index 4ebd7c76d..000000000 --- a/Tests/Functional/Entity/SymfonyConstraints80.php +++ /dev/null @@ -1,200 +0,0 @@ -propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; - } - - /** - * @Assert\Count(min="0", max="10") - */ - public function setPropertyNotBlank(int $propertyNotBlank): void - { - $this->propertyNotBlank = $propertyNotBlank; - } - - public function setPropertyNotNull(int $propertyNotNull): void - { - $this->propertyNotNull = $propertyNotNull; - } - - public function setPropertyAssertLength(int $propertyAssertLength): void - { - $this->propertyAssertLength = $propertyAssertLength; - } - - public function setPropertyRegex(int $propertyRegex): void - { - $this->propertyRegex = $propertyRegex; - } - - public function setPropertyCount(int $propertyCount): void - { - $this->propertyCount = $propertyCount; - } - - public function setPropertyChoice(int $propertyChoice): void - { - $this->propertyChoice = $propertyChoice; - } - - public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void - { - $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; - } - - public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void - { - $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; - } - - public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void - { - $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; - } - - public function setPropertyExpression(int $propertyExpression): void - { - $this->propertyExpression = $propertyExpression; - } - - public function setPropertyRange(int $propertyRange): void - { - $this->propertyRange = $propertyRange; - } - - public function setPropertyLessThan(int $propertyLessThan): void - { - $this->propertyLessThan = $propertyLessThan; - } - - public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void - { - $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; - } - - /** - * @return array - */ - public static function fetchAllowedChoices() - { - return ['choice1', 'choice2']; - } -} \ No newline at end of file From 2b0a418c22e7350699ffda5ac80e95f8e1ead0b1 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:41:24 +0100 Subject: [PATCH 49/54] test: fix php 7 SymfonyDiscriminator --- .../Functional/Controller/ApiController80.php | 4 +- .../Functional/Controller/ApiController81.php | 4 +- .../Entity/SymfonyDiscriminator.php | 43 ------------------- .../Entity/SymfonyDiscriminator81.php | 6 +-- .../Entity/SymfonyDiscriminatorOne.php | 2 +- .../Entity/SymfonyDiscriminatorTwo.php | 2 +- Tests/Functional/FunctionalTest.php | 6 ++- 7 files changed, 12 insertions(+), 55 deletions(-) delete mode 100644 Tests/Functional/Entity/SymfonyDiscriminator.php diff --git a/Tests/Functional/Controller/ApiController80.php b/Tests/Functional/Controller/ApiController80.php index 5d92d0717..e745e0abc 100644 --- a/Tests/Functional/Controller/ApiController80.php +++ b/Tests/Functional/Controller/ApiController80.php @@ -24,7 +24,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator80; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\SerializedNameEnt; @@ -317,7 +317,7 @@ public function compoundEntityAction() /** * @Route("/discriminator-mapping", methods={"GET", "POST"}) * - * @OA\Response(response=200, description="Worked well!", @Model(type=SymfonyDiscriminator::class)) + * @OA\Response(response=200, description="Worked well!", @Model(type=SymfonyDiscriminator80::class)) */ public function discriminatorMappingAction() { diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index 1e7d302ed..f9df3773a 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -16,6 +16,7 @@ use Nelmio\ApiDocBundle\Annotation\Security; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator81; use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\Symfony7\SerializedNameEntity; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; @@ -28,7 +29,6 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; use Nelmio\ApiDocBundle\Tests\Functional\Form\DummyType; @@ -255,7 +255,7 @@ public function compoundEntityAction() } #[Route('/discriminator-mapping', methods: ['GET', 'POST'])] - #[OA\Response(response: 200, description: 'Worked well!', attachables: [new Model(type: SymfonyDiscriminator::class)])] + #[OA\Response(response: 200, description: 'Worked well!', attachables: [new Model(type: SymfonyDiscriminator81::class)])] public function discriminatorMappingAction() { } diff --git a/Tests/Functional/Entity/SymfonyDiscriminator.php b/Tests/Functional/Entity/SymfonyDiscriminator.php deleted file mode 100644 index ea9a2258d..000000000 --- a/Tests/Functional/Entity/SymfonyDiscriminator.php +++ /dev/null @@ -1,43 +0,0 @@ - SymfonyDiscriminatorOne::class, 'two' => SymfonyDiscriminatorTwo::class] - )] - abstract class SymfonyDiscriminator - { - /** - * @var string - */ - public $type; - } -} diff --git a/Tests/Functional/Entity/SymfonyDiscriminator81.php b/Tests/Functional/Entity/SymfonyDiscriminator81.php index d82a0051e..9dbcb536c 100644 --- a/Tests/Functional/Entity/SymfonyDiscriminator81.php +++ b/Tests/Functional/Entity/SymfonyDiscriminator81.php @@ -17,10 +17,6 @@ typeProperty: 'type', mapping: ['one' => SymfonyDiscriminatorOne::class, 'two' => SymfonyDiscriminatorTwo::class] )] -abstract class SymfonyDiscriminator81 +abstract class SymfonyDiscriminator81 extends SymfonyDiscriminator80 { - /** - * @var string - */ - public $type; } \ No newline at end of file diff --git a/Tests/Functional/Entity/SymfonyDiscriminatorOne.php b/Tests/Functional/Entity/SymfonyDiscriminatorOne.php index 9d9aee69f..a67d00ca5 100644 --- a/Tests/Functional/Entity/SymfonyDiscriminatorOne.php +++ b/Tests/Functional/Entity/SymfonyDiscriminatorOne.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -class SymfonyDiscriminatorOne extends SymfonyDiscriminator implements SymfonyDiscriminatorFileMapping +class SymfonyDiscriminatorOne extends SymfonyDiscriminator80 implements SymfonyDiscriminatorFileMapping { /** * @var string diff --git a/Tests/Functional/Entity/SymfonyDiscriminatorTwo.php b/Tests/Functional/Entity/SymfonyDiscriminatorTwo.php index 01f6f4a54..4ee2c22aa 100644 --- a/Tests/Functional/Entity/SymfonyDiscriminatorTwo.php +++ b/Tests/Functional/Entity/SymfonyDiscriminatorTwo.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -class SymfonyDiscriminatorTwo extends SymfonyDiscriminator implements SymfonyDiscriminatorFileMapping +class SymfonyDiscriminatorTwo extends SymfonyDiscriminator80 implements SymfonyDiscriminatorFileMapping { /** * @var string diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index e36275f61..5566a62d8 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -620,7 +620,11 @@ public function testPrivateProtectedExposure() public function testModelsWithDiscriminatorMapAreLoadedWithOpenApiPolymorphism() { - $model = $this->getModel('SymfonyDiscriminator'); + if (TestKernel::isAttributesAvailable()) { + $model = $this->getModel('SymfonyDiscriminator81'); + } else { + $model = $this->getModel('SymfonyDiscriminator80'); + } $this->assertInstanceOf(OAAnnotations\Discriminator::class, $model->discriminator); $this->assertSame('type', $model->discriminator->propertyName); From da385b5053ca8f40b341460dd3cd4561d1a068c7 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:46:50 +0100 Subject: [PATCH 50/54] test: remove parent class SymfonyConstraints --- .../Functional/Controller/ApiController80.php | 4 +- .../Functional/Controller/ApiController81.php | 4 +- .../Functional/Entity/SymfonyConstraints.php | 207 ------------------ .../Entity/SymfonyConstraints80.php | 201 +++++++++++++++++ Tests/Functional/FunctionalTest.php | 10 +- 5 files changed, 213 insertions(+), 213 deletions(-) delete mode 100644 Tests/Functional/Entity/SymfonyConstraints.php create mode 100644 Tests/Functional/Entity/SymfonyConstraints80.php diff --git a/Tests/Functional/Controller/ApiController80.php b/Tests/Functional/Controller/ApiController80.php index e745e0abc..e41791c58 100644 --- a/Tests/Functional/Controller/ApiController80.php +++ b/Tests/Functional/Controller/ApiController80.php @@ -22,7 +22,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithNullableSchemaSet; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithObjectType; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints80; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator80; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; @@ -259,7 +259,7 @@ public function securityActionOverride() * response="201", * description="Used for symfony constraints test", * - * @Model(type=SymfonyConstraints::class) + * @Model(type=SymfonyConstraints80::class) * ) */ public function symfonyConstraintsAction() diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index f9df3773a..c8c52d308 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -27,7 +27,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithNullableSchemaSet; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithObjectType; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; @@ -214,7 +214,7 @@ public function securityActionOverride() #[OA\Response( response: '201', description: 'Used for symfony constraints test', - content: new Model(type: SymfonyConstraints::class), + content: new Model(type: SymfonyConstraints81::class), )] public function symfonyConstraintsAction() { diff --git a/Tests/Functional/Entity/SymfonyConstraints.php b/Tests/Functional/Entity/SymfonyConstraints.php deleted file mode 100644 index 451fc2830..000000000 --- a/Tests/Functional/Entity/SymfonyConstraints.php +++ /dev/null @@ -1,207 +0,0 @@ -propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; - } - - /** - * @Assert\Count(min="0", max="10") - */ - public function setPropertyNotBlank(int $propertyNotBlank): void - { - $this->propertyNotBlank = $propertyNotBlank; - } - - public function setPropertyNotNull(int $propertyNotNull): void - { - $this->propertyNotNull = $propertyNotNull; - } - - public function setPropertyAssertLength(int $propertyAssertLength): void - { - $this->propertyAssertLength = $propertyAssertLength; - } - - public function setPropertyRegex(int $propertyRegex): void - { - $this->propertyRegex = $propertyRegex; - } - - public function setPropertyCount(int $propertyCount): void - { - $this->propertyCount = $propertyCount; - } - - public function setPropertyChoice(int $propertyChoice): void - { - $this->propertyChoice = $propertyChoice; - } - - public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void - { - $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; - } - - public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void - { - $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; - } - - public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void - { - $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; - } - - public function setPropertyExpression(int $propertyExpression): void - { - $this->propertyExpression = $propertyExpression; - } - - public function setPropertyRange(int $propertyRange): void - { - $this->propertyRange = $propertyRange; - } - - public function setPropertyLessThan(int $propertyLessThan): void - { - $this->propertyLessThan = $propertyLessThan; - } - - public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void - { - $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; - } - - /** - * @return array - */ - public static function fetchAllowedChoices() - { - return ['choice1', 'choice2']; - } - } -} else { - class SymfonyConstraints extends SymfonyConstraints81 - { - } -} diff --git a/Tests/Functional/Entity/SymfonyConstraints80.php b/Tests/Functional/Entity/SymfonyConstraints80.php new file mode 100644 index 000000000..5dcfaf3b9 --- /dev/null +++ b/Tests/Functional/Entity/SymfonyConstraints80.php @@ -0,0 +1,201 @@ +propertyWithCompoundValidationRule = $propertyWithCompoundValidationRule; + } + + /** + * @Assert\Count(min="0", max="10") + */ + public function setPropertyNotBlank(int $propertyNotBlank): void + { + $this->propertyNotBlank = $propertyNotBlank; + } + + public function setPropertyNotNull(int $propertyNotNull): void + { + $this->propertyNotNull = $propertyNotNull; + } + + public function setPropertyAssertLength(int $propertyAssertLength): void + { + $this->propertyAssertLength = $propertyAssertLength; + } + + public function setPropertyRegex(int $propertyRegex): void + { + $this->propertyRegex = $propertyRegex; + } + + public function setPropertyCount(int $propertyCount): void + { + $this->propertyCount = $propertyCount; + } + + public function setPropertyChoice(int $propertyChoice): void + { + $this->propertyChoice = $propertyChoice; + } + + public function setPropertyChoiceWithCallback(int $propertyChoiceWithCallback): void + { + $this->propertyChoiceWithCallback = $propertyChoiceWithCallback; + } + + public function setPropertyChoiceWithCallbackWithoutClass(int $propertyChoiceWithCallbackWithoutClass): void + { + $this->propertyChoiceWithCallbackWithoutClass = $propertyChoiceWithCallbackWithoutClass; + } + + public function setPropertyChoiceWithMultiple(array $propertyChoiceWithMultiple): void + { + $this->propertyChoiceWithMultiple = $propertyChoiceWithMultiple; + } + + public function setPropertyExpression(int $propertyExpression): void + { + $this->propertyExpression = $propertyExpression; + } + + public function setPropertyRange(int $propertyRange): void + { + $this->propertyRange = $propertyRange; + } + + public function setPropertyLessThan(int $propertyLessThan): void + { + $this->propertyLessThan = $propertyLessThan; + } + + public function setPropertyLessThanOrEqual(int $propertyLessThanOrEqual): void + { + $this->propertyLessThanOrEqual = $propertyLessThanOrEqual; + } + + /** + * @return array + */ + public static function fetchAllowedChoices() + { + return ['choice1', 'choice2']; + } +} diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index 5566a62d8..e3a1df409 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -427,6 +427,12 @@ public function testClassSecurityAction() public function testSymfonyConstraintDocumentation() { + if (TestKernel::isAttributesAvailable()) { + $modelName = 'SymfonyConstraints81'; + } else { + $modelName = 'SymfonyConstraints80'; + } + $expected = [ 'required' => [ 'propertyNotBlank', @@ -496,7 +502,7 @@ public function testSymfonyConstraintDocumentation() ], ], 'type' => 'object', - 'schema' => 'SymfonyConstraints', + 'schema' => $modelName, ]; if (Helper::isCompoundValidatorConstraintSupported()) { @@ -510,7 +516,7 @@ public function testSymfonyConstraintDocumentation() ]; } - $this->assertEquals($expected, json_decode($this->getModel('SymfonyConstraints')->toJson(), true)); + $this->assertEquals($expected, json_decode($this->getModel($modelName)->toJson(), true)); } public function testConfigReference() From 3f7ded49e62256e4b4390adfe5b736fd438e389e Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 16:49:43 +0100 Subject: [PATCH 51/54] Revert "temp: remove fail-fast from ci" This reverts commit a8ac305bd787c09c63b729977e8c53671d558735. --- .github/workflows/continuous-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 2165a7e6e..d73a2395c 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -14,7 +14,7 @@ on: - master env: - fail-fast: false + fail-fast: true jobs: phpunit: From 5ba6a558b0d955461aee17b45ab2aead54c57557 Mon Sep 17 00:00:00 2001 From: DjordyKoert Date: Tue, 19 Dec 2023 17:01:36 +0100 Subject: [PATCH 52/54] phpcs --- Tests/Functional/BazingaFunctionalTest.php | 6 +- Tests/Functional/Entity/CustomDateTime.php | 3 +- .../Entity/EntityWithAlternateType80.php | 8 ++- .../Entity/EntityWithAlternateType81.php | 8 ++- Tests/Functional/FunctionalTest.php | 9 +-- Tests/Functional/TestKernel.php | 9 ++- Tests/Model/ModelRegistryTest.php | 3 +- .../Annotations/AnnotationReaderTest.php | 8 ++- .../Fixture/CompoundValidationRule.php | 3 +- .../SymfonyConstraintAnnotationReaderTest.php | 59 ++++++++++--------- .../SelfDescribingModelDescriberTest.php | 3 +- Tests/Render/RenderOpenApiTest.php | 5 +- Tests/RouteDescriber/FosRestDescriberTest.php | 3 +- .../RouteMetadataDescriberTest.php | 9 +-- .../FilteredRouteCollectionBuilderTest.php | 15 +++-- Tests/SwaggerPhp/UtilTest.php | 57 ++++++++++-------- Tests/Util/ControllerReflectorTest.php | 5 +- 17 files changed, 125 insertions(+), 88 deletions(-) diff --git a/Tests/Functional/BazingaFunctionalTest.php b/Tests/Functional/BazingaFunctionalTest.php index 92df0d95a..e09e08424 100644 --- a/Tests/Functional/BazingaFunctionalTest.php +++ b/Tests/Functional/BazingaFunctionalTest.php @@ -12,6 +12,8 @@ namespace Nelmio\ApiDocBundle\Tests\Functional; use Hateoas\Configuration\Embedded; +use ReflectionException; +use ReflectionMethod; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; @@ -103,8 +105,8 @@ public function testWithGroup() public function testWithType() { try { - new \ReflectionMethod(Embedded::class, 'getType'); - } catch (\ReflectionException $e) { + new ReflectionMethod(Embedded::class, 'getType'); + } catch (ReflectionException $e) { $this->markTestSkipped('Typed embedded properties require at least willdurand/hateoas 3.0'); } $this->assertEquals([ diff --git a/Tests/Functional/Entity/CustomDateTime.php b/Tests/Functional/Entity/CustomDateTime.php index 09af078be..aa20107f0 100644 --- a/Tests/Functional/Entity/CustomDateTime.php +++ b/Tests/Functional/Entity/CustomDateTime.php @@ -11,12 +11,13 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use DateTime; use JMS\Serializer\Annotation as Serializer; /** * @author Javier Spagnoletti */ -class CustomDateTime extends \DateTime +class CustomDateTime extends DateTime { /** * @Serializer\Type("string") diff --git a/Tests/Functional/Entity/EntityWithAlternateType80.php b/Tests/Functional/Entity/EntityWithAlternateType80.php index 348c03df4..90094651f 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType80.php +++ b/Tests/Functional/Entity/EntityWithAlternateType80.php @@ -11,22 +11,24 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use ArrayIterator; +use IteratorAggregate; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; /** * @OA\Schema(type="array", @OA\Items(type="string")) */ -class EntityWithAlternateType80 implements \IteratorAggregate +class EntityWithAlternateType80 implements IteratorAggregate { /** * @var string */ public $ignored = 'this property should be ignored because of the annotation above'; - public function getIterator(): \ArrayIterator + public function getIterator(): ArrayIterator { - return new \ArrayIterator([ + return new ArrayIterator([ 'abc', 'def', ]); diff --git a/Tests/Functional/Entity/EntityWithAlternateType81.php b/Tests/Functional/Entity/EntityWithAlternateType81.php index dcab95d8c..d405910a0 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType81.php +++ b/Tests/Functional/Entity/EntityWithAlternateType81.php @@ -11,20 +11,22 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; +use ArrayIterator; +use IteratorAggregate; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Attributes as OA; #[OA\Schema(type: 'array', items: new OA\Items(type: 'string'))] -class EntityWithAlternateType81 implements \IteratorAggregate +class EntityWithAlternateType81 implements IteratorAggregate { /** * @var string */ public $ignored = 'this property should be ignored because of the annotation above'; - public function getIterator(): \ArrayIterator + public function getIterator(): ArrayIterator { - return new \ArrayIterator([ + return new ArrayIterator([ 'abc', 'def', ]); diff --git a/Tests/Functional/FunctionalTest.php b/Tests/Functional/FunctionalTest.php index e3a1df409..70c913d36 100644 --- a/Tests/Functional/FunctionalTest.php +++ b/Tests/Functional/FunctionalTest.php @@ -18,6 +18,7 @@ use OpenApi\Attributes as OAAttributes; use OpenApi\Generator; use Symfony\Component\Serializer\Annotation\SerializedName; +use const PHP_VERSION_ID; class FunctionalTest extends WebTestCase { @@ -67,7 +68,7 @@ public function provideArticleRoute(): iterable yield 'Annotations' => ['/api/article/{id}']; } - if (\PHP_VERSION_ID >= 80100) { + if (PHP_VERSION_ID >= 80100) { yield 'Attributes' => ['/api/article_attributes/{id}']; } } @@ -379,7 +380,7 @@ public function provideSecurityRoute(): iterable { yield 'Annotations' => ['/api/security']; - if (\PHP_VERSION_ID >= 80100) { + if (PHP_VERSION_ID >= 80100) { yield 'Attributes' => ['/api/security_attributes']; } } @@ -397,14 +398,14 @@ public function provideSecurityOverrideRoute(): iterable { yield 'Annotations' => ['/api/securityOverride']; - if (\PHP_VERSION_ID >= 80100) { + if (PHP_VERSION_ID >= 80100) { yield 'Attributes' => ['/api/security_override_attributes']; } } public function testInlinePHP81Parameters() { - if (\PHP_VERSION_ID < 80100) { + if (PHP_VERSION_ID < 80100) { $this->markTestSkipped('Attributes require PHP 8.1'); } diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index 17a47d3f9..a94e31a27 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -24,7 +24,10 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\PrivateProtectedExposure; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; use Nelmio\ApiDocBundle\Tests\Functional\ModelDescriber\VirtualTypeClassDoesNotExistsHandlerDefinedDescriber; +use ReflectionException; +use ReflectionMethod; use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle; +use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\TwigBundle\TwigBundle; @@ -101,9 +104,9 @@ protected function configureRoutes($routes) $this->import($routes, __DIR__.'/Controller/BazingaController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); try { - new \ReflectionMethod(Embedded::class, 'getType'); + new ReflectionMethod(Embedded::class, 'getType'); $this->import($routes, __DIR__.'/Controller/BazingaTypedController.php', '/', self::isAnnotationsAvailable() ? 'annotation' : 'attribute'); - } catch (\ReflectionException $e) { + } catch (ReflectionException $e) { } } @@ -146,7 +149,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load ]; // Support symfony/framework-bundle < 5.4 - if (method_exists(\Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand::class, 'complete')) { + if (method_exists(CachePoolClearCommand::class, 'complete')) { $framework += [ 'exceptions' => [ 'Symfony\Component\HttpKernel\Exception\BadRequestHttpException' => [ diff --git a/Tests/Model/ModelRegistryTest.php b/Tests/Model/ModelRegistryTest.php index 59f559d7b..ddb2c8115 100644 --- a/Tests/Model/ModelRegistryTest.php +++ b/Tests/Model/ModelRegistryTest.php @@ -17,6 +17,7 @@ use OpenApi\Context; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use ReflectionClass; use Symfony\Component\PropertyInfo\Type; class ModelRegistryTest extends TestCase @@ -103,7 +104,7 @@ public function provideNameCollisionsTypes() public function testNameCollisionsAreLoggedWithAlternativeNames() { - $ref = new \ReflectionClass(self::class); + $ref = new ReflectionClass(self::class); $alternativeNames = [ $ref->getShortName() => [ 'type' => $ref->getName(), diff --git a/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php index 4aedd3798..505d7fe7b 100644 --- a/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/AnnotationReaderTest.php @@ -20,6 +20,8 @@ use OpenApi\Context; use OpenApi\Generator; use PHPUnit\Framework\TestCase; +use ReflectionProperty; +use const PHP_VERSION_ID; class AnnotationReaderTest extends TestCase { @@ -44,8 +46,8 @@ class_exists(AnnotationReader::class) ? new AnnotationReader() : null, $registry, ['json'] ); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property2'), $schema->properties[1]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property2'), $schema->properties[1]); $this->assertEquals($schema->properties[0]->example, 1); $this->assertEquals($schema->properties[0]->description, Generator::UNDEFINED); @@ -67,7 +69,7 @@ public function provideProperty(): iterable private $property2; }]; - if (\PHP_VERSION_ID >= 80100) { + if (PHP_VERSION_ID >= 80100) { yield 'Attributes' => [new class() { #[OAattr\Property(example: 1)] private $property1; diff --git a/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php b/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php index e6b5d3f74..cdfdd1802 100644 --- a/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php +++ b/Tests/ModelDescriber/Annotations/Fixture/CompoundValidationRule.php @@ -4,6 +4,7 @@ namespace Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture; +use Attribute; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints\Compound; @@ -14,7 +15,7 @@ class_alias(CompoundStub::class, Compound::class); /** * @Annotation */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] +#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final class CompoundValidationRule extends Compound { protected function getConstraints(array $options): array diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index f1766bad2..4e6bb29e0 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -20,9 +20,12 @@ use OpenApi\Context; use OpenApi\Generator; use PHPUnit\Framework\TestCase; +use ReflectionProperty; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints as Assert; +use function property_exists; +use const PHP_VERSION_ID; class SymfonyConstraintAnnotationReaderTest extends TestCase { @@ -70,8 +73,8 @@ public function testUpdatePropertyFix1283() $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property2'), $schema->properties[1]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property2'), $schema->properties[1]); // expect required to be numeric array with sequential keys (not [0 => ..., 2 => ...]) $this->assertEquals($schema->required, ['property1', 'property2']); @@ -84,7 +87,7 @@ public function testUpdatePropertyFix1283() */ public function testOptionalProperty($entity) { - if (!\property_exists(Assert\NotBlank::class, 'allowNull')) { + if (!property_exists(Assert\NotBlank::class, 'allowNull')) { $this->markTestSkipped('NotBlank::allowNull was added in symfony/validator 4.3.'); } @@ -95,8 +98,8 @@ public function testOptionalProperty($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property2'), $schema->properties[1]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property2'), $schema->properties[1]); // expect required to be numeric array with sequential keys (not [0 => ..., 2 => ...]) $this->assertEquals($schema->required, ['property2']); @@ -122,7 +125,7 @@ public function provideOptionalProperty(): iterable ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\NotBlank(allowNull: true)] #[Assert\Length(min: 1)] @@ -146,7 +149,7 @@ public function testAssertChoiceResultsInNumericArray($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); // expect enum to be numeric array with sequential keys (not [1 => "active", 2 => "active"]) $this->assertEquals($schema->properties[0]->enum, ['active', 'blocked']); @@ -172,7 +175,7 @@ public function provideAssertChoiceResultsInNumericArray(): iterable ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Length(min: 1)] #[Assert\Choice(choices: TEST_ASSERT_CHOICE_STATUSES)] @@ -194,7 +197,7 @@ public function testMultipleChoiceConstraintsApplyEnumToItems($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertInstanceOf(OA\Items::class, $schema->properties[0]->items); $this->assertEquals($schema->properties[0]->items->enum, ['one', 'two']); @@ -211,7 +214,7 @@ public function provideMultipleChoiceConstraintsApplyEnumToItems(): iterable }]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Choice(choices: ['one', 'two'], multiple: true)] private $property1; @@ -234,7 +237,7 @@ public function testLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertSame(Generator::UNDEFINED, $schema->properties[0]->maxLength); $this->assertSame(1, $schema->properties[0]->minLength); @@ -253,7 +256,7 @@ public function provideLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet(): itera ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Length(min: 1)] private $property1; @@ -276,7 +279,7 @@ public function testLengthConstraintDoesNotSetMinLengthIfMinIsNotSet($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertSame(Generator::UNDEFINED, $schema->properties[0]->minLength); $this->assertSame(100, $schema->properties[0]->maxLength); @@ -295,7 +298,7 @@ public function provideLengthConstraintDoesNotSetMinLengthIfMinIsNotSet(): itera ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Length(max: 100)] private $property1; @@ -326,7 +329,7 @@ public function testCompoundValidationRules() $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, $propertyName), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, $propertyName), $schema->properties[0]); if (Helper::isCompoundValidatorConstraintSupported()) { $this->assertSame([$propertyName], $schema->required); @@ -358,7 +361,7 @@ public function testCountConstraintDoesNotSetMinItemsIfMinIsNotSet($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertSame(Generator::UNDEFINED, $schema->properties[0]->minItems); $this->assertSame(10, $schema->properties[0]->maxItems); @@ -377,7 +380,7 @@ public function provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet(): iterabl ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Count(max: 10)] private $property1; @@ -400,7 +403,7 @@ public function testCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertSame(Generator::UNDEFINED, $schema->properties[0]->maxItems); $this->assertSame(10, $schema->properties[0]->minItems); @@ -419,7 +422,7 @@ public function provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet(): iterabl ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Count(min: 10)] private $property1; @@ -442,7 +445,7 @@ public function testRangeConstraintDoesNotSetMaximumIfMaxIsNotSet($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertSame(Generator::UNDEFINED, $schema->properties[0]->maximum); $this->assertSame(10, $schema->properties[0]->minimum); @@ -461,7 +464,7 @@ public function provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet(): iterable ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Range(min: 10)] private $property1; @@ -484,7 +487,7 @@ public function testRangeConstraintDoesNotSetMinimumIfMinIsNotSet($entity) $symfonyConstraintAnnotationReader = new SymfonyConstraintAnnotationReader($this->doctrineAnnotations); $symfonyConstraintAnnotationReader->setSchema($schema); - $symfonyConstraintAnnotationReader->updateProperty(new \ReflectionProperty($entity, 'property1'), $schema->properties[0]); + $symfonyConstraintAnnotationReader->updateProperty(new ReflectionProperty($entity, 'property1'), $schema->properties[0]); $this->assertSame(Generator::UNDEFINED, $schema->properties[0]->minimum); $this->assertSame(10, $schema->properties[0]->maximum); @@ -503,7 +506,7 @@ public function provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet(): iterable ]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\Range(max: 10)] private $property1; @@ -528,7 +531,7 @@ public function testReaderWithValidationGroupsEnabledChecksForDefaultGroupWhenNo // no serialization groups passed here $reader->updateProperty( - new \ReflectionProperty($entity, 'property1'), + new ReflectionProperty($entity, 'property1'), $schema->properties[0] ); @@ -551,7 +554,7 @@ public function testReaderWithValidationGroupsEnabledDoesNotReadAnnotationsWitho // no serialization groups passed here $reader->updateProperty( - new \ReflectionProperty($entity, 'property1'), + new ReflectionProperty($entity, 'property1'), $schema->properties[0] ); @@ -575,7 +578,7 @@ public function testReaderWithValidationGroupsEnabledReadsOnlyConstraintsWithGro // no serialization groups passed here $reader->updateProperty( - new \ReflectionProperty($entity, 'property1'), + new ReflectionProperty($entity, 'property1'), $schema->properties[0], ['other'] ); @@ -600,7 +603,7 @@ public function testReaderWithValidationGroupsEnabledCanReadFromMultipleValidati // no serialization groups passed here $reader->updateProperty( - new \ReflectionProperty($entity, 'property1'), + new ReflectionProperty($entity, 'property1'), $schema->properties[0], ['other', Constraint::DEFAULT_GROUP] ); @@ -622,7 +625,7 @@ public function provideConstraintsWithGroups(): iterable }]; } - if (\PHP_VERSION_ID >= 80000) { + if (PHP_VERSION_ID >= 80000) { yield 'Attributes' => [new class() { #[Assert\NotBlank()] #[Assert\Range(min: 1, groups: ['other'])] diff --git a/Tests/ModelDescriber/SelfDescribingModelDescriberTest.php b/Tests/ModelDescriber/SelfDescribingModelDescriberTest.php index 38decbe68..66045432b 100644 --- a/Tests/ModelDescriber/SelfDescribingModelDescriberTest.php +++ b/Tests/ModelDescriber/SelfDescribingModelDescriberTest.php @@ -16,6 +16,7 @@ use Nelmio\ApiDocBundle\Tests\ModelDescriber\Fixtures\SelfDescribingModel; use OpenApi\Annotations\Schema; use PHPUnit\Framework\TestCase; +use stdClass; use Symfony\Component\PropertyInfo\Type; class SelfDescribingModelDescriberTest extends TestCase @@ -31,7 +32,7 @@ public function testDoesNotSupport() { $describer = new SelfDescribingModelDescriber(); - $this->assertFalse($describer->supports(new Model(new Type('object', false, \stdClass::class)))); + $this->assertFalse($describer->supports(new Model(new Type('object', false, stdClass::class)))); } public function testDescribe() diff --git a/Tests/Render/RenderOpenApiTest.php b/Tests/Render/RenderOpenApiTest.php index c8d6cc164..514b0c822 100644 --- a/Tests/Render/RenderOpenApiTest.php +++ b/Tests/Render/RenderOpenApiTest.php @@ -11,6 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Render; +use InvalidArgumentException; use Nelmio\ApiDocBundle\Render\OpenApiRenderer; use Nelmio\ApiDocBundle\Render\RenderOpenApi; use OpenApi\Annotations\OpenApi; @@ -34,14 +35,14 @@ public function testRender() public function testUnknownFormat() { $availableOpenApiRenderers = []; - $this->expectExceptionObject(new \InvalidArgumentException(sprintf('Format "%s" is not supported.', $this->format))); + $this->expectExceptionObject(new InvalidArgumentException(sprintf('Format "%s" is not supported.', $this->format))); $this->renderOpenApi(...$availableOpenApiRenderers); } public function testUnknownArea() { $this->hasArea = false; - $this->expectExceptionObject(new \InvalidArgumentException(sprintf('Area "%s" is not supported.', $this->area))); + $this->expectExceptionObject(new InvalidArgumentException(sprintf('Area "%s" is not supported.', $this->area))); $this->renderOpenApi(); } diff --git a/Tests/RouteDescriber/FosRestDescriberTest.php b/Tests/RouteDescriber/FosRestDescriberTest.php index 5d94b7b42..acbd2e699 100644 --- a/Tests/RouteDescriber/FosRestDescriberTest.php +++ b/Tests/RouteDescriber/FosRestDescriberTest.php @@ -16,6 +16,7 @@ use Nelmio\ApiDocBundle\RouteDescriber\FosRestDescriber; use OpenApi\Annotations\OpenApi; use PHPUnit\Framework\TestCase; +use ReflectionMethod; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Routing\Route; use Symfony\Component\Validator\Constraints\Choice; @@ -47,7 +48,7 @@ public function testQueryParamWithChoiceConstraintIsAddedAsEnum() $fosRestDescriber->describe( $api, new Route('/'), - $this->createMock(\ReflectionMethod::class) + $this->createMock(ReflectionMethod::class) ); $this->assertSame($choices, $api->paths[0]->get->parameters[0]->schema->enum); diff --git a/Tests/RouteDescriber/RouteMetadataDescriberTest.php b/Tests/RouteDescriber/RouteMetadataDescriberTest.php index c8f61b98d..388720ed5 100644 --- a/Tests/RouteDescriber/RouteMetadataDescriberTest.php +++ b/Tests/RouteDescriber/RouteMetadataDescriberTest.php @@ -16,6 +16,7 @@ use OpenApi\Context; use OpenApi\Generator; use PHPUnit\Framework\TestCase; +use ReflectionMethod; use Symfony\Component\Routing\Route; class RouteMetadataDescriberTest extends TestCase @@ -24,7 +25,7 @@ public function testUndefinedCheck() { $routeDescriber = new RouteMetadataDescriber(); - $this->assertNull($routeDescriber->describe(new OpenApi(['_context' => new Context()]), new Route('foo'), new \ReflectionMethod(__CLASS__, 'testUndefinedCheck'))); + $this->assertNull($routeDescriber->describe(new OpenApi(['_context' => new Context()]), new Route('foo'), new ReflectionMethod(__CLASS__, 'testUndefinedCheck'))); } public function testRouteRequirementsWithPattern() @@ -35,7 +36,7 @@ public function testRouteRequirementsWithPattern() $routeDescriber->describe( $api, $route, - new \ReflectionMethod(__CLASS__, 'testRouteRequirementsWithPattern') + new ReflectionMethod(__CLASS__, 'testRouteRequirementsWithPattern') ); $this->assertEquals('/index/{bar}/{foo}.html', $api->paths[0]->path); @@ -59,7 +60,7 @@ public function testSimpleOrRequirementsAreHandledAsEnums($req) $routeDescriber->describe( $api, $route, - new \ReflectionMethod(__CLASS__, 'testSimpleOrRequirementsAreHandledAsEnums') + new ReflectionMethod(__CLASS__, 'testSimpleOrRequirementsAreHandledAsEnums') ); $this->assertEquals('/index/{bar}/{foo}.html', $api->paths[0]->path); @@ -82,7 +83,7 @@ public function testNonEnumPatterns($pattern) $routeDescriber->describe( $api, $route, - new \ReflectionMethod(__CLASS__, 'testNonEnumPatterns') + new ReflectionMethod(__CLASS__, 'testNonEnumPatterns') ); $getPathParameter = $api->paths[0]->get->parameters[0]; diff --git a/Tests/Routing/FilteredRouteCollectionBuilderTest.php b/Tests/Routing/FilteredRouteCollectionBuilderTest.php index d4f63b593..0c351456a 100644 --- a/Tests/Routing/FilteredRouteCollectionBuilderTest.php +++ b/Tests/Routing/FilteredRouteCollectionBuilderTest.php @@ -20,11 +20,14 @@ use OpenApi\Annotations\Parameter; use OpenApi\Context; use PHPUnit\Framework\TestCase; +use ReflectionMethod; +use stdClass; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\OptionsResolver\Exception\InvalidArgumentException; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; +use const PHP_VERSION_ID; /** * Tests for FilteredRouteCollectionBuilder class. @@ -121,7 +124,7 @@ public function getInvalidOptions(): array [['invalid_option' => []]], [['path_patterns' => [22]]], [['path_patterns' => [null]]], - [['path_patterns' => [new \stdClass()]]], + [['path_patterns' => [new stdClass()]]], [['path_patterns' => ['^/foo$', 1]]], [['with_annotation' => ['an array']]], [['path_patterns' => 'a string']], @@ -130,7 +133,7 @@ public function getInvalidOptions(): array [['name_patterns' => 'a string']], [['name_patterns' => [22]]], [['name_patterns' => [null]]], - [['name_patterns' => [new \stdClass()]]], + [['name_patterns' => [new stdClass()]]], ]; } @@ -180,7 +183,7 @@ public function getMatchingRoutes(): iterable ['r10', new Route('/api/areas/new'), ['path_patterns' => ['^/api']]], ]; - if (\PHP_VERSION_ID < 80000) { + if (PHP_VERSION_ID < 80000) { yield ['r10', new Route('/api/areas_attributes/new'), ['path_patterns' => ['^/api']]]; } } @@ -196,7 +199,7 @@ public function testMatchingRoutesWithAnnotation(string $name, Route $route, arr $routes->add($name, $route); $area = 'area'; - $reflectionMethodStub = $this->createMock(\ReflectionMethod::class); + $reflectionMethodStub = $this->createMock(ReflectionMethod::class); $controllerReflectorStub = $this->createMock(ControllerReflector::class); $controllerReflectorStub->method('getReflectionMethod')->willReturn($reflectionMethodStub); @@ -236,7 +239,7 @@ public function getMatchingRoutesWithAnnotation(): iterable ], ]; - if (\PHP_VERSION_ID < 80000) { + if (PHP_VERSION_ID < 80000) { yield from [ 'with attribute only' => [ 'r10', @@ -300,7 +303,7 @@ public function testRoutesWithDisabledDefaultRoutes( $routes->add($name, $route); $area = 'area'; - $reflectionMethodStub = $this->createMock(\ReflectionMethod::class); + $reflectionMethodStub = $this->createMock(ReflectionMethod::class); $controllerReflectorStub = $this->createMock(ControllerReflector::class); $controllerReflectorStub->method('getReflectionMethod')->willReturn($reflectionMethodStub); diff --git a/Tests/SwaggerPhp/UtilTest.php b/Tests/SwaggerPhp/UtilTest.php index 9e6fdfdd4..d1ab8df1c 100644 --- a/Tests/SwaggerPhp/UtilTest.php +++ b/Tests/SwaggerPhp/UtilTest.php @@ -11,11 +11,22 @@ namespace Nelmio\ApiDocBundle\Tests\SwaggerPhp; +use ArrayObject; +use Exception; use Nelmio\ApiDocBundle\OpenApiPhp\Util; use OpenApi\Annotations as OA; use OpenApi\Context; use OpenApi\Generator; use PHPUnit\Framework\TestCase; +use stdClass; +use function array_key_exists; +use function array_slice; +use function count; +use function get_class; +use function get_class_vars; +use function get_object_vars; +use function in_array; +use function strpos; /** * Class UtilTest. @@ -114,7 +125,7 @@ public function testCreateChildWithEmptyProperties() public function testCreateChildWithProperties() { - $properties = ['title' => 'testing', 'version' => '999', 'x' => new \stdClass()]; + $properties = ['title' => 'testing', 'version' => '999', 'x' => new stdClass()]; /** @var OA\Info $info */ $info = Util::createChild($this->rootAnnotation, OA\Info::class, $properties); @@ -174,12 +185,12 @@ public function testCreateCollectionItemDoesNotAddToUnknownProperty() public function testSearchCollectionItem() { - $item1 = new \stdClass(); + $item1 = new stdClass(); $item1->prop1 = 'item 1 prop 1'; $item1->prop2 = 'item 1 prop 2'; $item1->prop3 = 'item 1 prop 3'; - $item2 = new \stdClass(); + $item2 = new stdClass(); $item2->prop1 = 'item 2 prop 1'; $item2->prop2 = 'item 2 prop 2'; $item2->prop3 = 'item 2 prop 3'; @@ -202,7 +213,7 @@ public function testSearchCollectionItem() try { Util::searchCollectionItem($collection, array_merge(get_object_vars($item2), $search)); - } catch (\Exception $e) { + } catch (Exception $e) { echo $e->getMessage(); } @@ -222,7 +233,7 @@ public function testSearchIndexedCollectionItem($setup, $asserts) (Generator::UNDEFINED !== $setup['components']->{$collection} ? $setup['components']->{$collection} : []); // get the indexing correct within haystack preparation - $properties = array_fill(0, \count($setupCollection), null); + $properties = array_fill(0, count($setupCollection), null); // prepare the haystack array foreach ($items as $assertItem) { @@ -273,7 +284,7 @@ public function testGetIndexedCollectionItem($setup, $asserts) $setup['components']->{$collection} ?? []; // the children created within provider are not connected - if (!\in_array($child, $setupHaystack, true)) { + if (!in_array($child, $setupHaystack, true)) { $this->assertIsNested($itemParent, $child); $this->assertIsConnectedToRootContext($child); } @@ -386,7 +397,7 @@ public function testGetChild($setup, $asserts) $this->assertInstanceOf($assert['class'], $child); $this->assertSame($child, $parent->{$key}); - if (\array_key_exists($key, $setup)) { + if (array_key_exists($key, $setup)) { $this->assertSame($setup[$key], $parent->{$key}); } @@ -696,25 +707,25 @@ public function provideMergeData(): array 'assert' => array_merge( $assertDefaults, $merge, - ['tags' => \array_slice($merge['tags'], 0, 2, true)] + ['tags' => array_slice($merge['tags'], 0, 2, true)] ), ], [ // heavy nested merge array object 'setup' => $setupDefaults, - 'merge' => new \ArrayObject([ + 'merge' => new ArrayObject([ 'servers' => [ ['url' => 'http'], ['url' => 'https'], ], 'paths' => [ '/path/to/resource' => [ - 'get' => new \ArrayObject([ + 'get' => new ArrayObject([ 'responses' => [ '200' => [ '$ref' => '#/components/responses/default', ], ], - 'requestBody' => new \ArrayObject([ + 'requestBody' => new ArrayObject([ 'description' => 'request foo', 'content' => [ 'foo-request' => [ @@ -728,22 +739,22 @@ public function provideMergeData(): array ]), ], ], - 'tags' => new \ArrayObject([ + 'tags' => new ArrayObject([ ['name' => 'baz'], ['name' => 'foo'], - new \ArrayObject(['name' => 'baz']), + new ArrayObject(['name' => 'baz']), ['name' => 'foo'], ['name' => 'foo'], ]), - 'components' => new \ArrayObject([ + 'components' => new ArrayObject([ 'responses' => [ 'default' => [ 'description' => 'default response', - 'headers' => new \ArrayObject([ - 'foo-header' => new \ArrayObject([ - 'schema' => new \ArrayObject([ + 'headers' => new ArrayObject([ + 'foo-header' => new ArrayObject([ + 'schema' => new ArrayObject([ 'type' => 'array', - 'items' => new \ArrayObject([ + 'items' => new ArrayObject([ 'type' => 'string', 'enum' => ['foo', 'bar', 'baz'], ]), @@ -757,7 +768,7 @@ public function provideMergeData(): array 'assert' => array_merge( $assertDefaults, $merge, - ['tags' => \array_slice($merge['tags'], 0, 2, true)] + ['tags' => array_slice($merge['tags'], 0, 2, true)] ), ], [ // heavy nested merge swagger instance @@ -823,7 +834,7 @@ public function provideMergeData(): array 'assert' => array_merge( $assertDefaults, $merge, - ['tags' => \array_slice($merge['tags'], 0, 2, true)] + ['tags' => array_slice($merge['tags'], 0, 2, true)] ), ], ]; } @@ -851,11 +862,11 @@ private function getSetupPropertiesWithoutClass(array $setup) private function getNonDefaultProperties($object) { - $objectVars = \get_object_vars($object); - $classVars = \get_class_vars(\get_class($object)); + $objectVars = get_object_vars($object); + $classVars = get_class_vars(get_class($object)); $props = []; foreach ($objectVars as $key => $value) { - if ($value !== $classVars[$key] && 0 !== \strpos($key, '_')) { + if ($value !== $classVars[$key] && 0 !== strpos($key, '_')) { $props[$key] = $value; } } diff --git a/Tests/Util/ControllerReflectorTest.php b/Tests/Util/ControllerReflectorTest.php index 50a6408ff..d44b0dbde 100644 --- a/Tests/Util/ControllerReflectorTest.php +++ b/Tests/Util/ControllerReflectorTest.php @@ -5,6 +5,7 @@ use Nelmio\ApiDocBundle\Tests\Functional\Controller\BazingaController; use Nelmio\ApiDocBundle\Util\ControllerReflector; use PHPUnit\Framework\TestCase; +use ReflectionMethod; use Symfony\Component\DependencyInjection\Container; class ControllerReflectorTest extends TestCase @@ -13,11 +14,11 @@ public function testGetReflectionMethod(): void { $controllerReflector = new ControllerReflector(new Container()); $this->assertEquals( - \ReflectionMethod::class, + ReflectionMethod::class, get_class($controllerReflector->getReflectionMethod([BazingaController::class, 'userAction'])) ); $this->assertEquals( - \ReflectionMethod::class, + ReflectionMethod::class, get_class($controllerReflector->getReflectionMethod(BazingaController::class.'::userAction')) ); $this->assertNull( From adc739f2d57ce43d0dba34b7fe778feae8743332 Mon Sep 17 00:00:00 2001 From: Djordy Koert Date: Wed, 20 Dec 2023 14:29:02 +0100 Subject: [PATCH 53/54] style: apply styleci diff (#3) --- .../Functional/Controller/ApiController81.php | 13 +++-- .../Controller/ClassApiController80.php | 2 +- .../Controller/ClassApiController81.php | 2 +- .../Controller/FOSRestController.php | 2 +- .../Controller/InvokableController80.php | 2 +- .../Controller/InvokableController81.php | 2 +- Tests/Functional/Controller/JMSController.php | 3 +- .../Functional/Controller/JMSController81.php | 50 ++++++++--------- .../Entity/EntityWithAlternateType80.php | 3 +- .../Entity/EntityWithAlternateType81.php | 3 +- Tests/Functional/Entity/JMSComplex81.php | 20 +++---- Tests/Functional/Entity/JMSDualComplex.php | 2 +- .../Entity/JMSNamingStrategyConstraints.php | 2 - Tests/Functional/Entity/JMSNote.php | 2 +- Tests/Functional/Entity/JMSUser.php | 2 +- Tests/Functional/Entity/JMSUser81.php | 56 +++++++++---------- .../Entity/NestedGroup/JMSChat81.php | 2 +- .../Entity/NestedGroup/JMSChatRoom.php | 3 +- .../Entity/NestedGroup/JMSChatRoomUser.php | 2 +- .../Entity/NestedGroup/JMSChatUser.php | 2 +- .../Entity/NestedGroup/JMSChatUser81.php | 4 +- .../Entity/NestedGroup/JMSPicture.php | 1 - .../Entity/SymfonyConstraints80.php | 1 - .../Entity/SymfonyConstraints81.php | 2 +- ...mfonyConstraintsWithValidationGroups81.php | 2 +- .../Entity/SymfonyDiscriminator81.php | 2 +- Tests/Functional/Entity/VirtualProperty.php | 3 +- Tests/Functional/Entity/VirtualProperty81.php | 2 +- .../Form/FormWithAlternateSchemaType.php | 2 +- Tests/Functional/Form/FormWithRefType.php | 2 - Tests/Functional/Form/UserType.php | 1 - Tests/Functional/JMSFunctionalTest.php | 1 - Tests/Functional/TestKernel.php | 5 +- Tests/Functional/WebTestCase.php | 3 +- .../SymfonyConstraintAnnotationReaderTest.php | 16 +++--- 35 files changed, 104 insertions(+), 118 deletions(-) diff --git a/Tests/Functional/Controller/ApiController81.php b/Tests/Functional/Controller/ApiController81.php index c8c52d308..3b9fc8f94 100644 --- a/Tests/Functional/Controller/ApiController81.php +++ b/Tests/Functional/Controller/ApiController81.php @@ -13,14 +13,10 @@ use Nelmio\ApiDocBundle\Annotation\Areas; use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Annotation\Operation; use Nelmio\ApiDocBundle\Annotation\Security; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; -use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator81; -use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\Symfony7\SerializedNameEntity; -use OpenApi\Attributes as OA; -use Symfony\Component\Routing\Annotation\Route; -use Nelmio\ApiDocBundle\Annotation\Operation; use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArticleInterface; use Nelmio\ApiDocBundle\Tests\Functional\Entity\CompoundEntity; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithAlternateType81; @@ -29,13 +25,17 @@ use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithRef; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraints81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; +use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminator81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyDiscriminatorFileMapping; use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; +use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\Symfony7\SerializedNameEntity; use Nelmio\ApiDocBundle\Tests\Functional\Form\DummyType; use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithAlternateSchemaType; use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithModel; use Nelmio\ApiDocBundle\Tests\Functional\Form\FormWithRefType; use Nelmio\ApiDocBundle\Tests\Functional\Form\UserType; +use OpenApi\Attributes as OA; +use Symfony\Component\Routing\Annotation\Route; class ApiController81 { @@ -53,6 +53,7 @@ class ApiController81 public function fetchArticleAction() { } + #[OA\Get( responses: [ new OA\Response( @@ -61,7 +62,7 @@ public function fetchArticleAction() attachables: [ new Model(type: ArticleInterface::class, groups: ['light']), ], - ) + ), ], )] #[OA\Parameter(ref: '#/components/parameters/test')] diff --git a/Tests/Functional/Controller/ClassApiController80.php b/Tests/Functional/Controller/ClassApiController80.php index 2b341e2fc..6149184ab 100644 --- a/Tests/Functional/Controller/ClassApiController80.php +++ b/Tests/Functional/Controller/ClassApiController80.php @@ -30,4 +30,4 @@ class ClassApiController80 public function securityAction() { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/ClassApiController81.php b/Tests/Functional/Controller/ClassApiController81.php index ded9e9211..69c93b592 100644 --- a/Tests/Functional/Controller/ClassApiController81.php +++ b/Tests/Functional/Controller/ClassApiController81.php @@ -24,4 +24,4 @@ class ClassApiController81 public function securityAction() { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index 066a4dce8..a0bf4ae64 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -15,7 +15,7 @@ use Symfony\Component\Routing\Annotation\Route; if (TestKernel::isAttributesAvailable()) { - #[Route("/api", host: "api.example.com")] + #[Route('/api', host: 'api.example.com')] class FOSRestController extends FOSRestController81 { } diff --git a/Tests/Functional/Controller/InvokableController80.php b/Tests/Functional/Controller/InvokableController80.php index 85280296a..1f687601a 100644 --- a/Tests/Functional/Controller/InvokableController80.php +++ b/Tests/Functional/Controller/InvokableController80.php @@ -29,4 +29,4 @@ class InvokableController80 public function __invoke() { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/InvokableController81.php b/Tests/Functional/Controller/InvokableController81.php index 952b3bb9f..9d5f50e7c 100644 --- a/Tests/Functional/Controller/InvokableController81.php +++ b/Tests/Functional/Controller/InvokableController81.php @@ -24,4 +24,4 @@ class InvokableController81 public function __invoke() { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Controller/JMSController.php b/Tests/Functional/Controller/JMSController.php index 4cf8b5d51..705dba26a 100644 --- a/Tests/Functional/Controller/JMSController.php +++ b/Tests/Functional/Controller/JMSController.php @@ -22,9 +22,8 @@ class JMSController extends JMSController80 { } } else { - #[Route(host: "api.example.com")] + #[Route(host: 'api.example.com')] class JMSController extends JMSController81 { } } - diff --git a/Tests/Functional/Controller/JMSController81.php b/Tests/Functional/Controller/JMSController81.php index 529eedf24..d875d1d57 100644 --- a/Tests/Functional/Controller/JMSController81.php +++ b/Tests/Functional/Controller/JMSController81.php @@ -26,95 +26,95 @@ class JMSController81 { - #[Route("/api/jms", methods: ["GET"])] + #[Route('/api/jms', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", + description: 'Success', content: new Model(type: JMSUser::class) )] public function userAction() { } - #[Route("/api/yaml", methods: ["GET"])] + #[Route('/api/yaml', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", + description: 'Success', content: new Model(type: VirtualProperty::class) )] public function yamlAction() { } - #[Route("/api/jms_complex", methods: ["GET"])] + #[Route('/api/jms_complex', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", + description: 'Success', content: new Model( type: JMSComplex81::class, - groups: ["list", "details", "User" => ["list"]]) + groups: ['list', 'details', 'User' => ['list']]) )] public function complexAction() { } - #[Route("/api/jms_complex_dual", methods: ["GET"])] + #[Route('/api/jms_complex_dual', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", + description: 'Success', content: new Model( type: JMSDualComplex::class, - groups: ["Default", "complex" => ["User" => ["details"]]]) + groups: ['Default', 'complex' => ['User' => ['details']]]) )] public function complexDualAction() { } - #[Route("/api/jms_naming_strategy", methods: ["GET"])] + #[Route('/api/jms_naming_strategy', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", - content: new Model(type: JMSNamingStrategyConstraints::class, groups: ["Default"]) + description: 'Success', + content: new Model(type: JMSNamingStrategyConstraints::class, groups: ['Default']) )] public function namingStrategyConstraintsAction() { } - #[Route("/api/jms_chat", methods: ["GET"])] + #[Route('/api/jms_chat', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", - content: new Model(type: JMSChat::class, groups: ["Default", "members" => ["mini"]]) + description: 'Success', + content: new Model(type: JMSChat::class, groups: ['Default', 'members' => ['mini']]) )] public function chatAction() { } - #[Route("/api/jms_picture", methods: ["GET"])] + #[Route('/api/jms_picture', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", - content: new Model(type: JMSPicture::class, groups: ["mini"]) + description: 'Success', + content: new Model(type: JMSPicture::class, groups: ['mini']) )] public function pictureAction() { } - #[Route("/api/jms_mini_user", methods: ["GET"])] + #[Route('/api/jms_mini_user', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", - content: new Model(type: JMSChatUser::class, groups: ["mini"]) + description: 'Success', + content: new Model(type: JMSChatUser::class, groups: ['mini']) )] public function minUserAction() { } - #[Route("/api/jms_mini_user_nested", methods: ["GET"])] + #[Route('/api/jms_mini_user_nested', methods: ['GET'])] #[OA\Response( response: 200, - description: "Success", - content: new Model(type: JMSChatRoomUser::class, groups: ["mini", "friend" => ["living" => ["Default"]]]) + description: 'Success', + content: new Model(type: JMSChatRoomUser::class, groups: ['mini', 'friend' => ['living' => ['Default']]]) )] public function minUserNestedAction() { diff --git a/Tests/Functional/Entity/EntityWithAlternateType80.php b/Tests/Functional/Entity/EntityWithAlternateType80.php index 90094651f..9897feb99 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType80.php +++ b/Tests/Functional/Entity/EntityWithAlternateType80.php @@ -13,7 +13,6 @@ use ArrayIterator; use IteratorAggregate; -use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Annotations as OA; /** @@ -33,4 +32,4 @@ public function getIterator(): ArrayIterator 'def', ]); } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/EntityWithAlternateType81.php b/Tests/Functional/Entity/EntityWithAlternateType81.php index d405910a0..5f4f65436 100644 --- a/Tests/Functional/Entity/EntityWithAlternateType81.php +++ b/Tests/Functional/Entity/EntityWithAlternateType81.php @@ -13,7 +13,6 @@ use ArrayIterator; use IteratorAggregate; -use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use OpenApi\Attributes as OA; #[OA\Schema(type: 'array', items: new OA\Items(type: 'string'))] @@ -31,4 +30,4 @@ public function getIterator(): ArrayIterator 'def', ]); } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/JMSComplex81.php b/Tests/Functional/Entity/JMSComplex81.php index 014238d6f..21b59bfe2 100644 --- a/Tests/Functional/Entity/JMSComplex81.php +++ b/Tests/Functional/Entity/JMSComplex81.php @@ -15,37 +15,37 @@ use Nelmio\ApiDocBundle\Annotation\Model; use OpenApi\Attributes as OA; -#[Serializer\ExclusionPolicy("all")] +#[Serializer\ExclusionPolicy('all')] #[OA\Schema( - required: ["id", "user"], + required: ['id', 'user'], properties: [ new OA\Property( - property: "virtual", + property: 'virtual', ref: new Model(type: JMSUser::class) ), ], )] class JMSComplex81 { - #[Serializer\Type("integer")] + #[Serializer\Type('integer')] #[Serializer\Expose] - #[Serializer\Groups(["list"])] + #[Serializer\Groups(['list'])] private $id; #[OA\Property(ref: new Model(type: JMSUser::class))] #[Serializer\Expose] - #[Serializer\Groups(["details"])] - #[Serializer\SerializedName("user")] + #[Serializer\Groups(['details'])] + #[Serializer\SerializedName('user')] private $User; - #[Serializer\Type("string")] + #[Serializer\Type('string')] #[Serializer\Expose] - #[Serializer\Groups(["list"])] + #[Serializer\Groups(['list'])] private $name; #[Serializer\VirtualProperty] #[Serializer\Expose] - #[Serializer\Groups(["list"])] + #[Serializer\Groups(['list'])] #[OA\Property(ref: new Model(type: JMSUser::class))] public function getVirtualFriend() { diff --git a/Tests/Functional/Entity/JMSDualComplex.php b/Tests/Functional/Entity/JMSDualComplex.php index cac5e8fe2..1a4285d02 100644 --- a/Tests/Functional/Entity/JMSDualComplex.php +++ b/Tests/Functional/Entity/JMSDualComplex.php @@ -21,4 +21,4 @@ class JMSDualComplex extends JMSDualComplex80 class JMSDualComplex extends JMSDualComplex81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/JMSNamingStrategyConstraints.php b/Tests/Functional/Entity/JMSNamingStrategyConstraints.php index e6fbf72fc..029cbd8ae 100644 --- a/Tests/Functional/Entity/JMSNamingStrategyConstraints.php +++ b/Tests/Functional/Entity/JMSNamingStrategyConstraints.php @@ -11,9 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use JMS\Serializer\Annotation as Serializer; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; -use Symfony\Component\Validator\Constraints as Assert; if (TestKernel::isAnnotationsAvailable()) { class JMSNamingStrategyConstraints extends JMSNamingStrategyConstraints80 diff --git a/Tests/Functional/Entity/JMSNote.php b/Tests/Functional/Entity/JMSNote.php index 204fd93b5..96f46cbc9 100644 --- a/Tests/Functional/Entity/JMSNote.php +++ b/Tests/Functional/Entity/JMSNote.php @@ -21,4 +21,4 @@ class JMSNote extends JMSNote80 class JMSNote extends JMSNote81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/JMSUser.php b/Tests/Functional/Entity/JMSUser.php index 00a19774e..9184dab0f 100644 --- a/Tests/Functional/Entity/JMSUser.php +++ b/Tests/Functional/Entity/JMSUser.php @@ -21,4 +21,4 @@ class JMSUser extends JMSUser80 class JMSUser extends JMSUser81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/JMSUser81.php b/Tests/Functional/Entity/JMSUser81.php index 52e6e4418..9198e3718 100644 --- a/Tests/Functional/Entity/JMSUser81.php +++ b/Tests/Functional/Entity/JMSUser81.php @@ -17,25 +17,25 @@ /** * User. */ -#[Serializer\ExclusionPolicy("all")] +#[Serializer\ExclusionPolicy('all')] class JMSUser81 { - #[Serializer\Type("integer")] + #[Serializer\Type('integer')] #[Serializer\Expose] - #[Serializer\Groups(["list"])] - #[OA\Property(description: "User id", readOnly: true, title: "userid", example: 1, default: null)] + #[Serializer\Groups(['list'])] + #[OA\Property(description: 'User id', readOnly: true, title: 'userid', example: 1, default: null)] private $id; - #[Serializer\Type("int")] + #[Serializer\Type('int')] #[Serializer\Expose] - #[Serializer\SerializedName("daysOnline")] + #[Serializer\SerializedName('daysOnline')] #[OA\Property(default: 0, minimum: 1, maximum: 300)] private $daysOnline; - #[Serializer\Type("string")] + #[Serializer\Type('string')] #[Serializer\Expose] #[OA\Property(readOnly: false)] - #[Serializer\Groups(["details"])] + #[Serializer\Groups(['details'])] private $email; /** @@ -43,23 +43,23 @@ class JMSUser81 * * @var string[] */ - #[Serializer\Type("array")] - #[Serializer\Accessor(getter: "getRoles", setter: "setRoles")] + #[Serializer\Type('array')] + #[Serializer\Accessor(getter: 'getRoles', setter: 'setRoles')] #[Serializer\Expose] - #[OA\Property(default: ["user"], description: "Roles list", example: '["ADMIN","SUPERUSER"]', title: "roles")] + #[OA\Property(default: ['user'], description: 'Roles list', example: '["ADMIN","SUPERUSER"]', title: 'roles')] protected $roles; /** * User Location. */ - #[Serializer\Type("string")] + #[Serializer\Type('string')] #[Serializer\Expose] private $location; - #[Serializer\Type("string")] + #[Serializer\Type('string')] private $password; - #[OA\Property(property: "last_update", type: "date")] + #[OA\Property(property: 'last_update', type: 'date')] #[Serializer\Expose] private $updatedAt; @@ -77,7 +77,7 @@ class JMSUser81 #[Serializer\Expose] private $indexedFriends; - #[Serializer\Type("array")] + #[Serializer\Type('array')] #[Serializer\Expose] private $favoriteDates; @@ -85,10 +85,10 @@ class JMSUser81 #[Serializer\Expose] private $customDate; - #[Serializer\Type("integer")] + #[Serializer\Type('integer')] #[Serializer\Expose] - #[Serializer\SerializedName("friendsNumber")] - #[OA\Property(type: "string", minLength: 1, maxLength: 100)] + #[Serializer\SerializedName('friendsNumber')] + #[OA\Property(type: 'string', minLength: 1, maxLength: 100)] private $friendsNumber; #[Serializer\Type(User::class)] @@ -102,9 +102,9 @@ class JMSUser81 * * @var string */ - #[Serializer\Type("string")] + #[Serializer\Type('string')] #[Serializer\Expose] - #[OA\Property(enum: ["disabled", "enabled"])] + #[OA\Property(enum: ['disabled', 'enabled'])] private $status; /** @@ -112,7 +112,7 @@ class JMSUser81 * * @var string */ - #[Serializer\Type("VirtualTypeClassDoesNotExistsHandlerDefined")] + #[Serializer\Type('VirtualTypeClassDoesNotExistsHandlerDefined')] #[Serializer\Expose] private $virtualType1; @@ -121,31 +121,31 @@ class JMSUser81 * * @var string */ - #[Serializer\Type("VirtualTypeClassDoesNotExistsHandlerNotDefined")] + #[Serializer\Type('VirtualTypeClassDoesNotExistsHandlerNotDefined')] #[Serializer\Expose] private $virtualType2; - #[Serializer\Type("array>")] + #[Serializer\Type('array>')] #[Serializer\Expose] private $latLonHistory; - #[Serializer\Type("array")] + #[Serializer\Type('array')] #[Serializer\Expose] private $freeFormObject; - #[Serializer\Type("array")] + #[Serializer\Type('array')] #[Serializer\Expose] private $freeFormObjectWithoutType; - #[Serializer\Type("array>")] + #[Serializer\Type('array>')] #[Serializer\Expose] private $deepObject; - #[Serializer\Type("array>")] + #[Serializer\Type('array>')] #[Serializer\Expose] private $deepObjectWithItems; - #[Serializer\Type("array>>")] + #[Serializer\Type('array>>')] #[Serializer\Expose] private $deepFreeFormObjectCollection; diff --git a/Tests/Functional/Entity/NestedGroup/JMSChat81.php b/Tests/Functional/Entity/NestedGroup/JMSChat81.php index 9c44322b7..1bdf4ff19 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChat81.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChat81.php @@ -16,7 +16,7 @@ /** * User. */ -#[Serializer\ExclusionPolicy("all")] +#[Serializer\ExclusionPolicy('all')] class JMSChat81 { #[Serializer\Type('integer')] diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php b/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php index 9250cbf14..194122b62 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatRoom.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup; -use JMS\Serializer\Annotation as Serializer; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; if (TestKernel::isAnnotationsAvailable()) { @@ -22,4 +21,4 @@ class JMSChatRoom extends JMSChatRoom80 class JMSChatRoom extends JMSChatRoom81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php b/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php index f71b94c4b..3ee5556d4 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatRoomUser.php @@ -21,4 +21,4 @@ class JMSChatRoomUser extends JMSChatRoomUser80 class JMSChatRoomUser extends JMSChatRoomUser81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatUser.php b/Tests/Functional/Entity/NestedGroup/JMSChatUser.php index d364b2c7b..9ff0cdac8 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatUser.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatUser.php @@ -21,4 +21,4 @@ class JMSChatUser extends JMSChatUser80 class JMSChatUser extends JMSChatUser81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php b/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php index 834ceb728..ca8729957 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php +++ b/Tests/Functional/Entity/NestedGroup/JMSChatUser81.php @@ -16,7 +16,7 @@ /** * User. */ -#[Serializer\ExclusionPolicy("all")] +#[Serializer\ExclusionPolicy('all')] class JMSChatUser81 { #[Serializer\Type('integer')] @@ -24,7 +24,7 @@ class JMSChatUser81 private $id; #[Serializer\Type('Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup\JMSPicture')] - #[Serializer\Groups(["mini"])] + #[Serializer\Groups(['mini'])] #[Serializer\Expose] private $picture; diff --git a/Tests/Functional/Entity/NestedGroup/JMSPicture.php b/Tests/Functional/Entity/NestedGroup/JMSPicture.php index 98dbd8f2f..2de550c39 100644 --- a/Tests/Functional/Entity/NestedGroup/JMSPicture.php +++ b/Tests/Functional/Entity/NestedGroup/JMSPicture.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity\NestedGroup; - use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; if (TestKernel::isAnnotationsAvailable()) { diff --git a/Tests/Functional/Entity/SymfonyConstraints80.php b/Tests/Functional/Entity/SymfonyConstraints80.php index 5dcfaf3b9..3274a50c3 100644 --- a/Tests/Functional/Entity/SymfonyConstraints80.php +++ b/Tests/Functional/Entity/SymfonyConstraints80.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; -use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; use Nelmio\ApiDocBundle\Tests\ModelDescriber\Annotations\Fixture as CustomAssert; use Symfony\Component\Validator\Constraints as Assert; diff --git a/Tests/Functional/Entity/SymfonyConstraints81.php b/Tests/Functional/Entity/SymfonyConstraints81.php index c21d4e318..7ab8bb9d5 100644 --- a/Tests/Functional/Entity/SymfonyConstraints81.php +++ b/Tests/Functional/Entity/SymfonyConstraints81.php @@ -181,4 +181,4 @@ public static function fetchAllowedChoices() { return ['choice1', 'choice2']; } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups81.php b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups81.php index 0658f6387..609950221 100644 --- a/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups81.php +++ b/Tests/Functional/Entity/SymfonyConstraintsWithValidationGroups81.php @@ -37,4 +37,4 @@ class SymfonyConstraintsWithValidationGroups81 #[OA\Property(type: 'array', items: new OA\Items(type: 'string'))] #[Assert\Valid] public $propertyArray; -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/SymfonyDiscriminator81.php b/Tests/Functional/Entity/SymfonyDiscriminator81.php index 9dbcb536c..fad5da213 100644 --- a/Tests/Functional/Entity/SymfonyDiscriminator81.php +++ b/Tests/Functional/Entity/SymfonyDiscriminator81.php @@ -19,4 +19,4 @@ )] abstract class SymfonyDiscriminator81 extends SymfonyDiscriminator80 { -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/VirtualProperty.php b/Tests/Functional/Entity/VirtualProperty.php index 7e84ef72e..9be763b6f 100644 --- a/Tests/Functional/Entity/VirtualProperty.php +++ b/Tests/Functional/Entity/VirtualProperty.php @@ -12,7 +12,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use Nelmio\ApiDocBundle\Tests\Functional\TestKernel; -use JMS\Serializer\Annotation as Serializer; if (TestKernel::isAnnotationsAvailable()) { class VirtualProperty extends VirtualProperty80 @@ -22,4 +21,4 @@ class VirtualProperty extends VirtualProperty80 class VirtualProperty extends VirtualProperty81 { } -} \ No newline at end of file +} diff --git a/Tests/Functional/Entity/VirtualProperty81.php b/Tests/Functional/Entity/VirtualProperty81.php index aac0839e1..6c7857523 100644 --- a/Tests/Functional/Entity/VirtualProperty81.php +++ b/Tests/Functional/Entity/VirtualProperty81.php @@ -21,7 +21,7 @@ #[Serializer\VirtualProperty( name: 'email', exp: 'object.user.email', - options: [[Serializer\Type::class, ["string"]]] + options: [[Serializer\Type::class, ['string']]] )] class VirtualProperty81 { diff --git a/Tests/Functional/Form/FormWithAlternateSchemaType.php b/Tests/Functional/Form/FormWithAlternateSchemaType.php index 644468bd2..abe6253f1 100644 --- a/Tests/Functional/Form/FormWithAlternateSchemaType.php +++ b/Tests/Functional/Form/FormWithAlternateSchemaType.php @@ -43,4 +43,4 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ]); } } -} \ No newline at end of file +} diff --git a/Tests/Functional/Form/FormWithRefType.php b/Tests/Functional/Form/FormWithRefType.php index 7f998e96a..b1a40baaf 100644 --- a/Tests/Functional/Form/FormWithRefType.php +++ b/Tests/Functional/Form/FormWithRefType.php @@ -16,7 +16,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\HttpKernel\Kernel; if (PHP_VERSION_ID < 80100) { /** @@ -45,4 +44,3 @@ public function buildForm(FormBuilderInterface $builder, array $options): void } } } - diff --git a/Tests/Functional/Form/UserType.php b/Tests/Functional/Form/UserType.php index 717f0379d..4745d8e60 100644 --- a/Tests/Functional/Form/UserType.php +++ b/Tests/Functional/Form/UserType.php @@ -19,7 +19,6 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\OptionsResolver\OptionsResolver; if (PHP_VERSION_ID < 80100) { diff --git a/Tests/Functional/JMSFunctionalTest.php b/Tests/Functional/JMSFunctionalTest.php index 550350a5b..9bcc3c3b4 100644 --- a/Tests/Functional/JMSFunctionalTest.php +++ b/Tests/Functional/JMSFunctionalTest.php @@ -11,7 +11,6 @@ namespace Nelmio\ApiDocBundle\Tests\Functional; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; class JMSFunctionalTest extends WebTestCase diff --git a/Tests/Functional/TestKernel.php b/Tests/Functional/TestKernel.php index a94e31a27..a111df3ac 100644 --- a/Tests/Functional/TestKernel.php +++ b/Tests/Functional/TestKernel.php @@ -129,7 +129,6 @@ private function import($routes, $resource, $prefix, $type) protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) { - $framework = [ 'assets' => true, 'secret' => 'MySecretKey', @@ -140,7 +139,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load PHP_VERSION_ID >= 80100 && Kernel::MAJOR_VERSION < 7 ? ['enable_annotations' => true] : [] - ) + [ + ) + [ 'mapping' => [ 'paths' => [__DIR__.'/Resources/serializer/'], ], @@ -266,7 +265,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load 'alias' => 'JMSComplexDefault', 'type' => \Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex81::class, 'groups' => null, - ] + ], ]); } diff --git a/Tests/Functional/WebTestCase.php b/Tests/Functional/WebTestCase.php index 51b9b7951..c3e4cc260 100644 --- a/Tests/Functional/WebTestCase.php +++ b/Tests/Functional/WebTestCase.php @@ -14,7 +14,6 @@ use OpenApi\Annotations as OA; use OpenApi\Generator; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as BaseWebTestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\KernelInterface; class WebTestCase extends BaseWebTestCase @@ -171,7 +170,7 @@ public function assertNotHasProperty($property, OA\AbstractAnnotation $annotatio } /** - * BC symfony < 5.3 and symfony >= 7 + * BC symfony < 5.3 and symfony >= 7. * * KernelTestCase::getContainer has a Container return type object in symfony 7 * which is incompatible with the return type of previous versions or diff --git a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php index 4e6bb29e0..152b13a6e 100644 --- a/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php +++ b/Tests/ModelDescriber/Annotations/SymfonyConstraintAnnotationReaderTest.php @@ -121,7 +121,7 @@ public function provideOptionalProperty(): iterable * @Assert\NotBlank() */ private $property2; - } + }, ]; } @@ -171,7 +171,7 @@ public function provideAssertChoiceResultsInNumericArray(): iterable * @Assert\Choice(choices=TEST_ASSERT_CHOICE_STATUSES) */ private $property1; - } + }, ]; } @@ -252,7 +252,7 @@ public function provideLengthConstraintDoesNotSetMaxLengthIfMaxIsNotSet(): itera * @Assert\Length(min = 1) */ private $property1; - } + }, ]; } @@ -294,7 +294,7 @@ public function provideLengthConstraintDoesNotSetMinLengthIfMinIsNotSet(): itera * @Assert\Length(max = 100) */ private $property1; - } + }, ]; } @@ -376,7 +376,7 @@ public function provideCountConstraintDoesNotSetMinItemsIfMinIsNotSet(): iterabl * @Assert\Count(max = 10) */ private $property1; - } + }, ]; } @@ -418,7 +418,7 @@ public function provideCountConstraintDoesNotSetMaxItemsIfMaxIsNotSet(): iterabl * @Assert\Count(min = 10) */ private $property1; - } + }, ]; } @@ -460,7 +460,7 @@ public function provideRangeConstraintDoesNotSetMaximumIfMaxIsNotSet(): iterable * @Assert\Range(min = 10) */ private $property1; - } + }, ]; } @@ -502,7 +502,7 @@ public function provideRangeConstraintDoesNotSetMinimumIfMinIsNotSet(): iterable * @Assert\Range(max = 10) */ private $property1; - } + }, ]; } From e39987d152739fb6e1854fb61c487b1b7f67f89d Mon Sep 17 00:00:00 2001 From: Faizan Akram Dar Date: Wed, 20 Dec 2023 23:38:50 +0530 Subject: [PATCH 54/54] chore: removes duplicate line from continuous-integration.yml --- .github/workflows/continuous-integration.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index d73a2395c..240d96cc5 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -84,7 +84,6 @@ jobs: composer global config --no-plugins allow-plugins.symfony/flex true composer global require --no-progress --no-scripts --no-plugins symfony/flex composer update --no-interaction --no-progress ${{ matrix.composer-flags }} - composer update --no-interaction --no-progress ${{ matrix.composer-flags }} - name: PHPUnit Tests run: vendor/bin/simple-phpunit --configuration phpunit.xml.dist --coverage-text