Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for using cache pools with multiple areas #2232

Merged
merged 12 commits into from
Mar 6, 2024
Merged
6 changes: 3 additions & 3 deletions src/ApiDocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class ApiDocGenerator
/** @var CacheItemPoolInterface|null */
private $cacheItemPool;

/** @var string|null */
/** @var string */
private $cacheItemId;

/** @var string[] */
Expand All @@ -65,7 +65,7 @@ public function __construct($describers, $modelDescribers, CacheItemPoolInterfac
$this->describers = $describers;
$this->modelDescribers = $modelDescribers;
$this->cacheItemPool = $cacheItemPool;
$this->cacheItemId = $cacheItemId;
$this->cacheItemId = $cacheItemId ?? 'openapi_doc';
$this->generator = $generator ?? new Generator($this->logger);
}

Expand All @@ -91,7 +91,7 @@ public function generate(): OpenApi
}

if ($this->cacheItemPool) {
$item = $this->cacheItemPool->getItem($this->cacheItemId ?? 'openapi_doc');
$item = $this->cacheItemPool->getItem($this->cacheItemId);
if ($item->isHit()) {
return $this->openApi = $item->get();
}
Expand Down
13 changes: 13 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public function getConfigTreeBuilder(): TreeBuilder
'documentation' => [],
'name_patterns' => [],
'disable_default_routes' => false,
'cache' => [],
],
]
)
Expand Down Expand Up @@ -122,6 +123,18 @@ public function getConfigTreeBuilder(): TreeBuilder
->example(['info' => ['title' => 'My App']])
->prototype('variable')->end()
->end()
->arrayNode('cache')
->children()
->scalarNode('pool')
->info('define cache pool to use')
->defaultNull()
->end()
->scalarNode('item_id')
->info('define cache item id')
->defaultNull()
->end()
->end()
->end()
->end()
->end()
->end()
Expand Down
11 changes: 7 additions & 4 deletions src/DependencyInjection/NelmioApiDocExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,13 @@ public function load(array $configs, ContainerBuilder $container): void
$container->register('nelmio_api_doc.open_api.generator', Generator::class)
->setPublic(false);

$cachePool = isset($config['cache']['pool']) ? new Reference($config['cache']['pool']) : null;
$cacheItemId = $config['cache']['item_id'] ?? null;
$cachePool = $config['cache']['pool'] ?? null;
$cacheItemId = $config['cache']['item_id'] ?? 'openapi_doc';

foreach ($config['areas'] as $area => $areaConfig) {
$areaCachePool = $areaConfig['cache']['pool'] ?? $cachePool;
DjordyKoert marked this conversation as resolved.
Show resolved Hide resolved
$areaCacheItemId = $areaConfig['cache']['item_id'] ?? sprintf('%s.%s', $cacheItemId, $area);

$nameAliases = $this->findNameAliases($config['models']['names'], $area);
$container->register(sprintf('nelmio_api_doc.generator.%s', $area), ApiDocGenerator::class)
->setPublic(true)
Expand All @@ -99,8 +102,8 @@ public function load(array $configs, ContainerBuilder $container): void
->setArguments([
new TaggedIteratorArgument(sprintf('nelmio_api_doc.describer.%s', $area)),
new TaggedIteratorArgument('nelmio_api_doc.model_describer'),
$cachePool,
$cacheItemId,
null !== $areaCachePool ? new Reference($areaCachePool) : null,
$areaCacheItemId,
new Reference('nelmio_api_doc.open_api.generator'),
]);

Expand Down
146 changes: 127 additions & 19 deletions tests/DependencyInjection/NelmioApiDocExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Nelmio\ApiDocBundle\DependencyInjection\NelmioApiDocExtension;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class NelmioApiDocExtensionTest extends TestCase
{
Expand Down Expand Up @@ -151,41 +152,148 @@ public function testMergesRootKeysFromMultipleConfigurations()
], $container->getDefinition('nelmio_api_doc.describers.config')->getArgument(0));
}

public function testApiDocGeneratorWithCachePool()
/**
* @dataProvider provideCacheConfig
*/
public function testApiDocGeneratorWithCachePool(array $config, array $expectedValues)
{
$container = new ContainerBuilder();
$container->setParameter('kernel.bundles', []);

$extension = new NelmioApiDocExtension();
$extension->load([
[
'documentation' => [
'info' => [
'title' => 'API documentation',
'description' => 'This is the api documentation, use it wisely',
],
],
$extension->load([$config], $container);

$reference = $container->getDefinition('nelmio_api_doc.generator.default')->getArgument(2);
if (null === $expectedValues['defaultCachePool']) {
$this->assertNull($reference);
} else {
$this->assertInstanceOf(Reference::class, $reference);
$this->assertSame($expectedValues['defaultCachePool'], (string) $reference);
}

$reference = $container->getDefinition('nelmio_api_doc.generator.area1')->getArgument(2);
if (null === $expectedValues['area1CachePool']) {
$this->assertNull($reference);
} else {
$this->assertInstanceOf(Reference::class, $reference);
$this->assertSame($expectedValues['area1CachePool'], (string) $reference);
}

$cacheItemId = $container->getDefinition('nelmio_api_doc.generator.default')->getArgument(3);
$this->assertSame($expectedValues['defaultCacheItemId'], $cacheItemId);

$cacheItemId = $container->getDefinition('nelmio_api_doc.generator.area1')->getArgument(3);
$this->assertSame($expectedValues['area1CacheItemId'], $cacheItemId);
}

public static function provideCacheConfig(): iterable
{
yield 'default cache.item_id & area appending' => [
'config' => [
'cache' => [
'pool' => 'test.cache',
'item_id' => 'nelmio.docs',
],
'areas' => [
'default' => [],
'area1' => [],
],
],
], $container);
'expectedValues' => [
'defaultCachePool' => 'test.cache',
'defaultCacheItemId' => 'openapi_doc.default',
'area1CachePool' => 'test.cache',
'area1CacheItemId' => 'openapi_doc.area1',
],
];

$reference = $container->getDefinition('nelmio_api_doc.generator.default')->getArgument(2);
$this->assertSame('test.cache', (string) $reference);
yield 'configuring cache.item_id & area appending' => [
'config' => [
'cache' => [
'pool' => 'test.cache',
'item_id' => 'test.docs',
],
'areas' => [
'default' => [],
'area1' => [],
],
],
'expectedValues' => [
'defaultCachePool' => 'test.cache',
'defaultCacheItemId' => 'test.docs.default',
'area1CachePool' => 'test.cache',
'area1CacheItemId' => 'test.docs.area1',
],
];

$reference = $container->getDefinition('nelmio_api_doc.generator.area1')->getArgument(2);
$this->assertSame('test.cache', (string) $reference);
yield 'overwriting item_id for an area' => [
'config' => [
'cache' => [
'pool' => 'test.cache',
'item_id' => 'nelmio.docs',
],
'areas' => [
'default' => [
'cache' => [
'pool' => 'test.cache.default',
'item_id' => 'nelmio.docs.default',
],
],
'area1' => [],
],
],
'expectedValues' => [
'defaultCachePool' => 'test.cache.default',
'defaultCacheItemId' => 'nelmio.docs.default',
'area1CachePool' => 'test.cache',
'area1CacheItemId' => 'nelmio.docs.area1',
],
];

$cacheItemId = $container->getDefinition('nelmio_api_doc.generator.default')->getArgument(3);
$this->assertSame('nelmio.docs', $cacheItemId);
yield 'setting cache for a single area' => [
'config' => [
'areas' => [
'default' => [
],
'area1' => [
'cache' => [
'pool' => 'app.cache',
'item_id' => 'docs',
],
],
],
],
'expectedValues' => [
'defaultCachePool' => null,
'defaultCacheItemId' => 'openapi_doc.default',
'area1CachePool' => 'app.cache',
'area1CacheItemId' => 'docs',
],
];

$cacheItemId = $container->getDefinition('nelmio_api_doc.generator.area1')->getArgument(3);
$this->assertSame('nelmio.docs', $cacheItemId);
yield 'setting a global cache pool & shared item_id' => [
'config' => [
'cache' => [
'pool' => 'app.cache',
],
'areas' => [
'default' => [
'cache' => [
'item_id' => 'docs',
],
],
'area1' => [
'cache' => [
'item_id' => 'docs',
],
],
],
],
'expectedValues' => [
'defaultCachePool' => 'app.cache',
'defaultCacheItemId' => 'docs',
'area1CachePool' => 'app.cache',
'area1CacheItemId' => 'docs',
],
];
}
}