Suppress the generation of operationId in the contract
Is it possible to suppress the generation of the operationId?
Currently the operationId is generated with a hash value if the attribute operationId is missing for an operation.
This causes strange behaviour with the OpenAPI-Generator for language java. Besides that this needs to be fixed at the OpenAPI-Generator, is it possible to omit the operationId easily?
There is an issue with this topic, but it has no clear instructions how to omit the operationId: https://github.com/zircote/swagger-php/issues/930 Some improvements to operationId were added here: https://github.com/zircote/swagger-php/pull/942
Trying to instantiate the Generator manually is not allowed:
$generator = (new Generator())->updateProcessor(new OperationId(false));
$openapi = $generator::scan(['api']);
Fatal error: Uncaught Error: The "Generator" class is reserved for internal use and cannot be manually instantiated in C:\xxx\api-docs.php:25 Stack trace: #0 {main} thrown in C:\xxx\api-docs.php on line 25
So how can the operationId be omitted generally?
This can currently be solved by overriding the operationId in the OpenApi\Processors\OperationId.php:
public function __invoke(Analysis $analysis)
{
...
if ($operationId) {
$operationId = strtoupper($operation->method) . '::' . $operation->path . '::' . $operationId;
$operation->operationId = $this->hash ? md5($operationId) : $operationId;
// RESET operationId: alway override the operationId to UNDEFINED
$operation->operationId = Generator::UNDEFINED;
}
Not a clean solution, but for now it works...
Depends on how you are using swagger-php. Programmatically you always have the option to remove a processor from the pipeline.
$generator = new Generator();
// ....
$generator->removeProcessor($processor);
Only downside right now is that processors are compared using ===, so you'd have to find the actually registered instance, for example:
$processors = $generator->getProcessors();
$operationIdProcessor = null;
foreach ($processors as $processor) {
if ($processor instanceof OperationId) {
$operationIdProcessor = $processor;
break;
}
}
$generator->removeProcessor($operationIdProcessor);
I just tried that, the OperationId-Processor is actually removed from the processors. However, it still is invoked during the scan process:
$generator = new \OpenApi\Generator;
$processors = $generator->getProcessors();
$operationIdProcessor = null;
foreach ($processors as $processor) {
if ($processor instanceof OperationId) {
echo "*** Found OperationId-Processor";
$operationIdProcessor = $processor;
break;
}
}
// OperationId-Process is here:
var_dump($generator->getProcessors());
var_dump($operationIdProcessor);
$generator->removeProcessor($operationIdProcessor);
// OperationId-Process is removed:
var_dump($generator->getProcessors());
$openapi = $generator::scan(...);
// OperationId-Processor invoke is still called!
The scan() method is static, so it doesn't really know about the changed processors in $generator. It should really be deprecated; in this case you really want to call $generator->generate().
If you insist on using scan() then that should look something like this:
Generator::scan($sources, ['processors' => $generator->getProcessors());
scan is the static, untyped version of generate(). You can set all options it accepts using fluid methods on $generator:
public static function scan(iterable $sources, array $options = []): ?OA\OpenApi
{
// merge with defaults
$config = $options + [
'aliases' => self::DEFAULT_ALIASES,
'namespaces' => self::DEFAULT_NAMESPACES,
'analyser' => null,
'analysis' => null,
'processors' => null,
'logger' => null,
'validate' => true,
'version' => null,
];
return (new Generator($config['logger']))
->setVersion($config['version'])
->setAliases($config['aliases'])
->setNamespaces($config['namespaces'])
->setAnalyser($config['analyser'])
->setProcessors($config['processors'])
->generate($sources, $config['analysis'], $config['validate']);
}