Skip to content

Commit

Permalink
Merge branch 'master' into ci/php-8.2-8.3
Browse files Browse the repository at this point in the history
  • Loading branch information
GuilhemN authored Dec 31, 2023
2 parents 46552a8 + 83e7fdd commit 0f06cff
Show file tree
Hide file tree
Showing 122 changed files with 9,838 additions and 1,321 deletions.
47 changes: 33 additions & 14 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,56 +22,75 @@ jobs:
runs-on: "ubuntu-22.04"

strategy:
fail-fast: false
matrix:
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.*"
- php-version: 8.2
symfony-require: "5.4.*"
- php-version: 8.2
symfony-require: "6.3.*"
doctrine-annotations: true
- php-version: 8.3
symfony-require: "5.4.*"
doctrine-annotations: true
- php-version: 8.3
symfony-require: "6.3.*"
doctrine-annotations: true
- php-version: 8.1
symfony-require: "7.0.*"
doctrine-annotations: false
- php-version: 8.3
symfony-require: "7.0.*"
doctrine-annotations: false

steps:
- name: "Checkout"
uses: "actions/checkout@v4"
uses: actions/checkout@v4
with:
fetch-depth: 2

- name: "Install PHP without coverage"
uses: "shivammathur/setup-php@v2"
uses: shivammathur/setup-php@v2
with:
php-version: "${{ matrix.php-version }}"
tools: "composer, flex"
tools: composer, flex
coverage: pcov

- name: Get composer cache directory
- name: "Get composer cache directory"
id: composercache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache dependencies
- name: "Cache dependencies"
uses: actions/cache@v3
with:
path: ${{ steps.composercache.outputs.dir }}
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: |
composer remove friendsofsymfony/rest-bundle sensio/framework-extra-bundle --no-update --dev
- name: "Install dependencies with composer"
env:
SYMFONY_REQUIRE: "${{ matrix.symfony-require }}"
run: |
composer update --no-interaction --no-progress ${{ matrix.composer-flags }}
run: composer update --no-interaction --no-progress ${{ matrix.composer-flags }}

- name: PHPUnit Tests
run: vendor/bin/simple-phpunit --configuration phpunit.xml.dist --coverage-text
- name: "PHPUnit Tests"
run: vendor/bin/phpunit --configuration phpunit.xml.dist --coverage-text
6 changes: 3 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ jobs:

steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: "Create cache dir"
run: mkdir .cache

- name: "Extract base branch name"
run: echo "##[set-output name=branch;]$(echo ${GITHUB_BASE_REF:=${GITHUB_REF##*/}})"
run: echo "branch=$(echo ${GITHUB_BASE_REF:=${GITHUB_REF##*/}})" >> $GITHUB_OUTPUT
id: extract_base_branch

- name: "Cache DOCtor-RST"
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: .cache
key: ${{ runner.os }}-doctor-rst-${{ steps.extract_base_branch.outputs.branch }}
Expand Down
5 changes: 1 addition & 4 deletions Command/DumpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
3 changes: 2 additions & 1 deletion DependencyInjection/Compiler/ConfigurationPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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]);
Expand Down
7 changes: 4 additions & 3 deletions DependencyInjection/NelmioApiDocExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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'),
Expand Down
26 changes: 20 additions & 6 deletions Describer/OpenApiPhpDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -65,16 +69,26 @@ 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) {
$classAnnotations = [];
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()])) {
Expand Down
8 changes: 1 addition & 7 deletions ModelDescriber/Annotations/AnnotationsReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
19 changes: 12 additions & 7 deletions ModelDescriber/Annotations/OpenApiAnnotationsReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 8 additions & 6 deletions ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SymfonyConstraintAnnotationReader
use SetsContextTrait;

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

Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions ModelDescriber/FormModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ final class FormModelDescriber implements ModelDescriberInterface, ModelRegistry
use SetsContextTrait;

private $formFactory;

/**
* @var Reader|null
*/
private $doctrineReader;
private $mediaTypes;
private $useValidationGroups;
Expand All @@ -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'];
Expand Down
5 changes: 4 additions & 1 deletion ModelDescriber/JMSModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class JMSModelDescriber implements ModelDescriberInterface, ModelRegistryAwareIn

private $namingStrategy;

/**
* @var Reader|null
*/
private $doctrineReader;

private $contexts = [];
Expand All @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions ModelDescriber/ObjectModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion Render/Json/JsonOpenApiRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ public function render(OpenApi $spec, array $options = []): string
];
$flags = $options['no-pretty'] ? 0 : JSON_PRETTY_PRINT;

return json_encode($spec, $flags);
return json_encode($spec, $flags | JSON_UNESCAPED_SLASHES);
}
}
Loading

0 comments on commit 0f06cff

Please sign in to comment.