Skip to content

Commit

Permalink
Add support for generator / processor configuration (#1211)
Browse files Browse the repository at this point in the history
  • Loading branch information
DerManoMann authored May 3, 2022
1 parent 86e2466 commit 22cec77
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 20 deletions.
53 changes: 49 additions & 4 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,23 @@ class Generator
/** @var string Magic value to differentiate between null and undefined. */
public const UNDEFINED = '@OA\Generator::UNDEFINED🙈';

/** @var string[] */
/** @var array<string,string> */
public const DEFAULT_ALIASES = ['oa' => 'OpenApi\\Annotations'];
/** @var string[] */
/** @var array<string> */
public const DEFAULT_NAMESPACES = ['OpenApi\\Annotations\\'];

/** @var array Map of namespace aliases to be supported by doctrine. */
/** @var array<string,string> Map of namespace aliases to be supported by doctrine. */
protected $aliases;

/** @var array|null List of annotation namespaces to be autoloaded by doctrine. */
/** @var array<string>|null List of annotation namespaces to be autoloaded by doctrine. */
protected $namespaces;

/** @var AnalyserInterface|null The configured analyzer. */
protected $analyser;

/** @var array<string,mixed> */
protected $config = [];

/** @var callable[]|null List of configured processors. */
protected $processors = null;

Expand Down Expand Up @@ -177,6 +180,32 @@ public function setAnalyser(?AnalyserInterface $analyser): Generator
return $this;
}

public function getDefaultConfig(): array
{
return [
'operationId' => [
'hash' => true,
],
];
}

public function getConfig(): array
{
return $this->config + $this->getDefaultConfig();
}

/**
* Set generator and/or processor config.
*
* @param array<string,mixed> $config
*/
public function setConfig(array $config): Generator
{
$this->config = $config + $this->config;

return $this;
}

/**
* @return callable[]
*/
Expand All @@ -203,6 +232,22 @@ public function getProcessors(): array
];
}

$config = $this->getConfig();
foreach ($this->processors as $processor) {
$rc = new \ReflectionClass($processor);

// apply config
$processorKey = lcfirst($rc->getShortName());
if (array_key_exists($processorKey, $config)) {
foreach ($config[$processorKey] as $name => $value) {
$setter = 'set' . ucfirst($name);
if (method_exists($processor, $setter)) {
$processor->{$setter}($value);
}
}
}
}

return $this->processors;
}

Expand Down
26 changes: 13 additions & 13 deletions src/Processors/ExpandClasses.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
use OpenApi\Generator;

/**
* Iterate over the chain of anchestors of a schema and:
* - merge anchestor annotations/methods/properties into the schema if the anchestor doesn't have a schema itself
* - inherit from the anchestor if it has a schema (allOf) and stop.
* Iterate over the chain of ancestors of a schema and:
* - merge ancestor annotations/methods/properties into the schema if the ancestor doesn't have a schema itself
* - inherit from the ancestor if it has a schema (allOf) and stop.
*/
class ExpandClasses
{
Expand All @@ -27,20 +27,20 @@ public function __invoke(Analysis $analysis)

foreach ($schemas as $schema) {
if ($schema->_context->is('class')) {
$anchestors = $analysis->getSuperClasses($schema->_context->fullyQualifiedName($schema->_context->class));
$ancestors = $analysis->getSuperClasses($schema->_context->fullyQualifiedName($schema->_context->class));
$existing = [];
foreach ($anchestors as $anchestor) {
$anchestorSchema = $analysis->getSchemaForSource($anchestor['context']->fullyQualifiedName($anchestor['class']));
if ($anchestorSchema) {
$refPath = !Generator::isDefault($anchestorSchema->schema) ? $anchestorSchema->schema : $anchestor['class'];
$this->inheritFrom($analysis, $schema, $anchestorSchema, $refPath, $anchestor['context']);
foreach ($ancestors as $ancestor) {
$ancestorSchema = $analysis->getSchemaForSource($ancestor['context']->fullyQualifiedName($ancestor['class']));
if ($ancestorSchema) {
$refPath = !Generator::isDefault($ancestorSchema->schema) ? $ancestorSchema->schema : $ancestor['class'];
$this->inheritFrom($analysis, $schema, $ancestorSchema, $refPath, $ancestor['context']);

// one anchestor is enough
// one ancestor is enough
break;
} else {
$this->mergeAnnotations($schema, $anchestor, $existing);
$this->mergeMethods($schema, $anchestor, $existing);
$this->mergeProperties($schema, $anchestor, $existing);
$this->mergeAnnotations($schema, $ancestor, $existing);
$this->mergeMethods($schema, $ancestor, $existing);
$this->mergeProperties($schema, $ancestor, $existing);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Processors/ExpandInterfaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __invoke(Analysis $analysis)
$interfaces = $analysis->getInterfacesOfClass($className, true);

if (class_exists($className) && ($parent = get_parent_class($className)) && ($inherited = array_keys(class_implements($parent)))) {
// strip interfaces we inherit from anchestor
// strip interfaces we inherit from ancestor
foreach (array_keys($interfaces) as $interface) {
if (in_array(ltrim($interface, '\\'), $inherited)) {
unset($interfaces[$interface]);
Expand Down
34 changes: 32 additions & 2 deletions tests/GeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ public function testScanInvalidSource(): void
public function processorCases(): iterable
{
return [
[new OperationId(false), false],
[new OperationId(true), true],
[new OperationId(), true],
[new class(false) extends OperationId {
}, false],
];
Expand Down Expand Up @@ -116,4 +115,35 @@ public function testRemoveProcessorNotFound(): void
(new Generator())->removeProcessor(function () {
});
}

protected function assertOperationIdHash(Generator $generator, bool $expected)
{
foreach ($generator->getProcessors() as $processor) {
if ($processor instanceof OperationId) {
$this->assertEquals($expected, $processor->isHash());
}
}
}

public function testConfig()
{
$generator = new Generator();
$this->assertOperationIdHash($generator, true);

$generator->setConfig(['operationId' => ['hash' => false]]);
$this->assertOperationIdHash($generator, false);
}

public function testCallableProcessor()
{
$generator = new Generator();
// not the default
$operationId = new OperationId(false);
$generator->addProcessor(function (Analysis $analysis) use ($operationId) {
$operationId($analysis);
});

$this->assertOperationIdHash($generator, true);
$this->assertFalse($operationId->isHash());
}
}

0 comments on commit 22cec77

Please sign in to comment.