Skip to content

Commit

Permalink
Merge branch 'master' into add/custom-processors
Browse files Browse the repository at this point in the history
  • Loading branch information
DjordyKoert authored Jan 2, 2024
2 parents 187b845 + 5130757 commit 4e9ce03
Show file tree
Hide file tree
Showing 124 changed files with 10,812 additions and 1,340 deletions.
56 changes: 42 additions & 14 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,81 @@ env:
jobs:
phpunit:
name: "PHPUnit"
runs-on: "ubuntu-20.04"
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.4
symfony-require: "5.4.*"
doctrine-annotations: true
- php-version: 8.1
symfony-require: "6.3.*"
doctrine-annotations: true
- php-version: 8.4
symfony-require: "6.3.*"
doctrine-annotations: true
- php-version: 8.2
symfony-require: "7.0.*"
doctrine-annotations: false
- php-version: 8.3
symfony-require: "7.0.*"
doctrine-annotations: false
- php-version: 8.4
symfony-require: "7.0.*"
doctrine-annotations: false

steps:
- name: "Checkout"
uses: "actions/checkout@v2"
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
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
uses: actions/cache@v2
- 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 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 }}
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
15 changes: 14 additions & 1 deletion ApiDocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ final class ApiDocGenerator

/** @var string[] */
private $mediaTypes = ['json'];
/**
* @var ?string
*/
private $openApiVersion = null;

/** @var Generator */
private $generator;
Expand All @@ -62,7 +66,7 @@ public function __construct($describers, $modelDescribers, CacheItemPoolInterfac
$this->modelDescribers = $modelDescribers;
$this->cacheItemPool = $cacheItemPool;
$this->cacheItemId = $cacheItemId;
$this->generator = $generator ?? new Generator();
$this->generator = $generator ?? new Generator($this->logger);
}

public function setAlternativeNames(array $alternativeNames)
Expand All @@ -75,6 +79,11 @@ public function setMediaTypes(array $mediaTypes)
$this->mediaTypes = $mediaTypes;
}

public function setOpenApiVersion(?string $openApiVersion)
{
$this->openApiVersion = $openApiVersion;
}

public function generate(): OpenApi
{
if (null !== $this->openApi) {
Expand All @@ -88,6 +97,10 @@ public function generate(): OpenApi
}
}

if ($this->openApiVersion) {
$this->generator->setVersion($this->openApiVersion);
}

$this->generator->setProcessors($this->getProcessors($this->generator));

$context = Util::createContext(['version' => $this->generator->getVersion()]);
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ You MUST follow the [PSR-1](http://www.php-fig.org/psr/psr-1/) and
should really read the recommendations. Can't wait? Use the [PHP-CS-Fixer
tool](http://cs.sensiolabs.org/).

You MUST run the test suite (run `composer update`, and then execute `vendor/bin/simple-phpunit`).
You MUST run the test suite (run `composer update`, and then execute `composer run phpunit`).

You MUST write (or update) unit tests.

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
8 changes: 5 additions & 3 deletions DependencyInjection/NelmioApiDocExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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 @@ -80,6 +81,7 @@ public function load(array $configs, ContainerBuilder $container): void
->addMethodCall('setAlternativeNames', [$nameAliases])
->addMethodCall('setMediaTypes', [$config['media_types']])
->addMethodCall('setLogger', [new Reference('logger')])
->addMethodCall('setOpenApiVersion', [$config['documentation']['openapi'] ?? null])
->addTag('monolog.logger', ['channel' => 'nelmio_api_doc'])
->setArguments([
new TaggedIteratorArgument(sprintf('nelmio_api_doc.describer.%s', $area)),
Expand All @@ -103,7 +105,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 @@ -132,7 +134,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 @@ -190,7 +192,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
Loading

0 comments on commit 4e9ce03

Please sign in to comment.