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

add support for versioning #2129

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion Annotation/Model.php
Expand Up @@ -49,6 +49,11 @@ final class Model extends Attachable
*/
public $options;

/**
* @var string[]
*/
public $versions;

/**
* @param mixed[] $properties
* @param string[] $groups
Expand All @@ -58,12 +63,14 @@ public function __construct(
array $properties = [],
string $type = Generator::UNDEFINED,
array $groups = null,
array $options = null
array $options = null,
array $versions = null
) {
parent::__construct($properties + [
'type' => $type,
'groups' => $groups,
'options' => $options,
'versions' => $versions,
]);
}
}
7 changes: 7 additions & 0 deletions DependencyInjection/Configuration.php
Expand Up @@ -127,6 +127,13 @@ public function getConfigTreeBuilder(): TreeBuilder
->thenInvalid('Model groups must be either `null` or an array.')
->end()
->end()
->variableNode('versions')
->defaultValue(null)
->validate()
->ifTrue(function ($v) { return null !== $v && !is_array($v); })
->thenInvalid('Model versions must be either `null` or an array.')
->end()
->end()
->arrayNode('areas')
->defaultValue([])
->prototype('scalar')->end()
Expand Down
1 change: 1 addition & 0 deletions DependencyInjection/NelmioApiDocExtension.php
Expand Up @@ -239,6 +239,7 @@ private function findNameAliases(array $names, string $area): array
$aliases[$nameAlias['alias']] = [
'type' => $nameAlias['type'],
'groups' => $nameAlias['groups'],
'versions' => $nameAlias['versions'],
];
}

Expand Down
16 changes: 14 additions & 2 deletions Model/Model.php
Expand Up @@ -21,14 +21,18 @@ final class Model

private $options;

private $versions;

/**
* @param string[]|null $groups
* @param string[]|null $versions
*/
public function __construct(Type $type, array $groups = null, array $options = null)
public function __construct(Type $type, array $groups = null, array $options = null, array $versions = null)
{
$this->type = $type;
$this->groups = $groups;
$this->options = $options;
$this->versions = $versions;
}

/**
Expand All @@ -39,6 +43,14 @@ public function getType()
return $this->type;
}

/**
* @return string[]|null
*/
public function getVersions()
{
return $this->versions;
}

/**
* @return string[]|null
*/
Expand All @@ -49,7 +61,7 @@ public function getGroups()

public function getHash(): string
{
return md5(serialize([$this->type, $this->groups]));
return md5(serialize([$this->type, $this->groups, $this->versions ?: null]));
}

/**
Expand Down
5 changes: 3 additions & 2 deletions Model/ModelRegistry.php
Expand Up @@ -48,7 +48,7 @@ public function __construct($modelDescribers, OA\OpenApi $api, array $alternativ
$this->api = $api;
$this->logger = new NullLogger();
foreach (array_reverse($alternativeNames) as $alternativeName => $criteria) {
$this->alternativeNames[] = $model = new Model(new Type('object', false, $criteria['type']), $criteria['groups']);
$this->alternativeNames[] = $model = new Model(new Type('object', false, $criteria['type']), $criteria['groups'], null, $criteria['versions']);
$this->names[$model->getHash()] = $alternativeName;
$this->registeredModelNames[$alternativeName] = $model;
Util::getSchema($this->api, $alternativeName);
Expand Down Expand Up @@ -128,7 +128,7 @@ private function generateModelName(Model $model): string
$i = 1;
while (\in_array($name, $names, true)) {
if (isset($this->registeredModelNames[$name])) {
$this->logger->info(sprintf('Can not assign a name for the model, the name "%s" has already been taken.', $name), [
$this->logger->error(sprintf('Can not assign a name for the model, the name "%s" has already been taken.', $name), [
'model' => $this->modelToArray($model),
'taken_by' => $this->modelToArray($this->registeredModelNames[$name]),
]);
Expand Down Expand Up @@ -157,6 +157,7 @@ private function modelToArray(Model $model): array
'type' => $getType($model->getType()),
'options' => $model->getOptions(),
'groups' => $model->getGroups(),
'versions' => $model->getVersions(),
];
}

Expand Down
3 changes: 2 additions & 1 deletion ModelDescriber/ApplyOpenApiDiscriminatorTrait.php
Expand Up @@ -54,7 +54,8 @@ protected function applyOpenApiDiscriminator(
$oneOfSchema->ref = $modelRegistry->register(new Model(
new Type(Type::BUILTIN_TYPE_OBJECT, false, $className),
$model->getGroups(),
$model->getOptions()
$model->getOptions(),
$model->getVersions()
));
$schema->oneOf[] = $oneOfSchema;
$schema->discriminator->mapping[$propertyValue] = $oneOfSchema->ref;
Expand Down
4 changes: 4 additions & 0 deletions ModelDescriber/JMSModelDescriber.php
Expand Up @@ -15,6 +15,7 @@
use JMS\Serializer\Context;
use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface;
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\SerializationContext;
use Metadata\MetadataFactoryInterface;
Expand Down Expand Up @@ -197,6 +198,9 @@ public function getSerializationContext(Model $model): SerializationContext
if (null !== $model->getGroups()) {
$context->addExclusionStrategy(new GroupsExclusionStrategy($model->getGroups()));
}
if (null !== $model->getVersions()) {
$context->addExclusionStrategy(new VersionExclusionStrategy($model->getVersions()[0]));
}
}

return $context;
Expand Down
6 changes: 3 additions & 3 deletions OpenApiPhp/ModelRegister.php
Expand Up @@ -45,7 +45,7 @@ public function __invoke(Analysis $analysis, array $parentGroups = null)
if ($annotation instanceof OA\Schema && $annotation->ref instanceof ModelAnnotation) {
$model = $annotation->ref;

$annotation->ref = $this->modelRegistry->register(new Model($this->createType($model->type), $this->getGroups($model, $parentGroups), $model->options));
$annotation->ref = $this->modelRegistry->register(new Model($this->createType($model->type), $this->getGroups($model, $parentGroups), $model->options, $model->versions));

// It is no longer an unmerged annotation
$this->detach($model, $annotation, $analysis);
Expand All @@ -71,7 +71,7 @@ public function __invoke(Analysis $analysis, array $parentGroups = null)
if ($annotation instanceof OA\Response || $annotation instanceof OA\RequestBody) {
$properties = [
'_context' => Util::createContext(['nested' => $annotation], $annotation->_context),
'ref' => $this->modelRegistry->register(new Model($this->createType($model->type), $this->getGroups($model, $parentGroups), $model->options)),
'ref' => $this->modelRegistry->register(new Model($this->createType($model->type), $this->getGroups($model, $parentGroups), $model->options, $model->versions)),
];

foreach ($this->mediaTypes as $mediaType) {
Expand All @@ -98,7 +98,7 @@ public function __invoke(Analysis $analysis, array $parentGroups = null)
}

$annotation->merge([new $annotationClass([
'ref' => $this->modelRegistry->register(new Model($this->createType($model->type), $this->getGroups($model, $parentGroups), $model->options)),
'ref' => $this->modelRegistry->register(new Model($this->createType($model->type), $this->getGroups($model, $parentGroups), $model->options, $model->versions)),
])]);

// It is no longer an unmerged annotation
Expand Down