Skip to content

Commit

Permalink
POC for custom processors
Browse files Browse the repository at this point in the history
  • Loading branch information
Luehrsen committed Nov 16, 2023
1 parent bd10c34 commit 80ce859
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 6 deletions.
54 changes: 48 additions & 6 deletions ApiDocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use OpenApi\Analysis;
use OpenApi\Annotations\OpenApi;
use OpenApi\Generator;
use OpenApi\Processors\ProcessorInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Log\LoggerAwareTrait;

Expand Down Expand Up @@ -48,6 +49,9 @@ final class ApiDocGenerator
/** @var string[] */
private $mediaTypes = ['json'];

/** @var array<ProcessorInterface|callable> */
private $processors = [];

/**
* @param DescriberInterface[]|iterable $describers
* @param ModelDescriberInterface[]|iterable $modelDescribers
Expand Down Expand Up @@ -84,12 +88,8 @@ public function generate(): OpenApi
}

$generator = new Generator();
// Remove OperationId processor as we use a lot of generated annotations which do not have enough information in their context
// to generate these ids properly.
// @see https://github.com/zircote/swagger-php/issues/1153
$generator->setProcessors(array_filter($generator->getProcessors(), function ($processor) {
return !$processor instanceof \OpenApi\Processors\OperationId;
}));

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

$context = Util::createContext(['version' => $generator->getVersion()]);

Expand Down Expand Up @@ -125,4 +125,46 @@ public function generate(): OpenApi

return $this->openApi;
}

/**
* Get an array of processors that will be used to process the OpenApi object.
*
* @param Generator $generator The generator instance to get the standard processors from.
*
* @return array<ProcessorInterface|callable> The array of processors.
*/
private function getProcessors(Generator $generator): array
{
// Get the standard processors from the generator.
$processors = $generator->getProcessors();

// Remove OperationId processor as we use a lot of generated annotations which do not have enough information in their context
// to generate these ids properly.
// @see \Nelmio\ApiDocBundle\OpenApiPhp\Util::createContext
foreach ($processors as $key => $processor) {
if ($processor instanceof \OpenApi\Processors\OperationId) {
unset($processors[$key]);
}
}

// Add our custom processors.
foreach ($this->processors as $processor) {
// Instantiate the processor.
$processors[] = new $processor();
}

return $processors;
}

/**
* Register a processor to be used to process the OpenApi object.
*
* @param ProcessorInterface|callable $processor The processor to register.
*
* @return void
*/
public function registerProcessor($processor): void
{
$this->processors[] = $processor;
}
}
60 changes: 60 additions & 0 deletions DependencyInjection/Compiler/CustomProcessorPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

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

namespace Nelmio\ApiDocBundle\DependencyInjection\Compiler;

use Nelmio\ApiDocBundle\ApiDocGenerator;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
* Compiler Pass to identify and register custom processors.
* *
* @internal
*/
final class CustomProcessorPass implements CompilerPassInterface
{
/**
* Process services tagged as 'swagger.processor'.
*
* @param ContainerBuilder $container The container builder
*
* @return void
*/
public function process(ContainerBuilder $container): void
{
$definitions = [];
// Find all registered generator services.
foreach($container->getDefinitions() as $id => $definition) {
// Check if the service-id contains the tag 'nelmio_api_doc.generator'
if (strpos($id, 'nelmio_api_doc.generator.') === false) {
continue;
}

$definitions[$id] = $definition;
}

// If the ApiDocGenerator service is not defined, then there is nothing to do
if (!$container->has(ApiDocGenerator::class)) {
return;
}

$definition = $container->getDefinition(ApiDocGenerator::class);
$processors = [];
foreach ($container->findTaggedServiceIds('swagger.processor') as $id => $tags) {
$processors[] = $id;
}

foreach($processors as $processor) {
$definition->addMethodCall('registerProcessor', [$processor]);
}
}
}
2 changes: 2 additions & 0 deletions NelmioApiDocBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Nelmio\ApiDocBundle;

use Nelmio\ApiDocBundle\DependencyInjection\Compiler\ConfigurationPass;
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\CustomProcessorPass;
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\PhpDocExtractorPass;
use Nelmio\ApiDocBundle\DependencyInjection\Compiler\TagDescribersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand All @@ -27,5 +28,6 @@ public function build(ContainerBuilder $container): void
$container->addCompilerPass(new ConfigurationPass());
$container->addCompilerPass(new TagDescribersPass());
$container->addCompilerPass(new PhpDocExtractorPass());
$container->addCompilerPass(new CustomProcessorPass());
}
}

0 comments on commit 80ce859

Please sign in to comment.