Make sure alternative names use the exact names specified (#1384)

* Make sure alternative names use the exact name specified

* Document the feature

* Cs
This commit is contained in:
Guilhem N 2018-08-26 22:15:44 +02:00 committed by GitHub
parent df9893428e
commit 31ae375ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 33 deletions

View File

@ -91,9 +91,12 @@ final class Configuration implements ConfigurationInterface
->children() ->children()
->scalarNode('alias')->isRequired()->end() ->scalarNode('alias')->isRequired()->end()
->scalarNode('type')->isRequired()->end() ->scalarNode('type')->isRequired()->end()
->arrayNode('groups') ->variableNode('groups')
->defaultValue([]) ->defaultValue(null)
->variablePrototype()->end() ->validate()
->ifTrue(function ($v) { return null !== $v && !is_array($v); })
->thenInvalid('Model groups must be either `null` or an array.')
->end()
->end() ->end()
->arrayNode('areas') ->arrayNode('areas')
->defaultValue([]) ->defaultValue([])

View File

@ -41,16 +41,28 @@ final class ModelRegistry
$this->modelDescribers = $modelDescribers; $this->modelDescribers = $modelDescribers;
$this->api = $api; $this->api = $api;
$this->alternativeNames = array_reverse($alternativeNames); // last rule wins $this->alternativeNames = array_reverse($alternativeNames); // last rule wins
foreach ($this->alternativeNames as $alternativeName => $criteria) {
$this->doRegister(new Model(new Type('object', false, $criteria['type']), $criteria['groups']), $alternativeName);
}
} }
public function register(Model $model): string public function register(Model $model): string
{
return $this->doRegister($model);
}
/**
* Private method allowing to enforce the model name for alternative names.
*/
private function doRegister(Model $model, string $name = null)
{ {
$hash = $model->getHash(); $hash = $model->getHash();
if (isset($this->names[$hash])) { if (isset($this->names[$hash])) {
return '#/definitions/'.$this->names[$hash]; return '#/definitions/'.$this->names[$hash];
} }
$this->names[$hash] = $name = $this->generateModelName($model); $this->names[$hash] = $name = ($name ?? $this->generateModelName($model));
$this->models[$hash] = $model; $this->models[$hash] = $model;
$this->unregistered[] = $hash; $this->unregistered[] = $hash;
@ -99,7 +111,7 @@ final class ModelRegistry
{ {
$definitions = $this->api->getDefinitions(); $definitions = $this->api->getDefinitions();
$name = $base = $this->getAlternativeName($model) ?? $this->getTypeShortName($model->getType()); $name = $base = $this->getTypeShortName($model->getType());
$i = 1; $i = 1;
while ($definitions->has($name)) { while ($definitions->has($name)) {
@ -110,27 +122,6 @@ final class ModelRegistry
return $name; return $name;
} }
/**
* @param Model $model
*
* @return string|null
*/
private function getAlternativeName(Model $model)
{
$type = $model->getType();
foreach ($this->alternativeNames as $alternativeName => $criteria) {
if (
Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType() &&
$type->getClassName() === $criteria['type'] &&
$criteria['groups'] == $model->getGroups()
) {
return $alternativeName;
}
}
return null;
}
private function getTypeShortName(Type $type): string private function getTypeShortName(Type $type): string
{ {
if (null !== $type->getCollectionValueType()) { if (null !== $type->getCollectionValueType()) {

View File

@ -26,3 +26,26 @@ In this case the class ``App\Entity\User`` will be aliased into:
- ``MainUser_light`` when the group is equal to ``light`` - ``MainUser_light`` when the group is equal to ``light``
- ``MainUser_secret`` for the ``private`` area - ``MainUser_secret`` for the ``private`` area
- ``MainUser`` for the ``private`` area when the group is equal to ``standard`` - ``MainUser`` for the ``private`` area when the group is equal to ``standard``
.. tip::
This allows to use normal references instead of ``@Model``. Notably, you can specify
the groups used for a model once in config and then refer to its alternative name:
.. code-block:: yaml
nelmio_api_doc:
models:
names: [ { alias: MyModel, type: App\MyModel, groups: [light] }]
.. code-block:: php
class HomeController
{
/**
* @SWG\Response(response=200, @SWG\Schema(ref="MyModel"))
*/
public function indexAction()
{
}
}

View File

@ -92,7 +92,7 @@ class ConfigurationTest extends TestCase
[ [
'alias' => 'Foo3', 'alias' => 'Foo3',
'type' => 'App\Foo', 'type' => 'App\Foo',
'groups' => [], 'groups' => null,
'areas' => [], 'areas' => [],
], ],
[ [
@ -104,7 +104,7 @@ class ConfigurationTest extends TestCase
[ [
'alias' => 'Foo1', 'alias' => 'Foo1',
'type' => 'App\\Foo', 'type' => 'App\\Foo',
'groups' => [], 'groups' => null,
'areas' => ['internal'], 'areas' => ['internal'],
], ],
[ [

View File

@ -53,11 +53,11 @@ class NelmioApiDocExtensionTest extends TestCase
$this->assertEquals([ $this->assertEquals([
'Foo1' => [ 'Foo1' => [
'type' => 'App\\Foo', 'type' => 'App\\Foo',
'groups' => [], 'groups' => null,
], ],
'Test1' => [ 'Test1' => [
'type' => 'App\\Test', 'type' => 'App\\Test',
'groups' => [], 'groups' => null,
], ],
], $methodCall[1][0]); ], $methodCall[1][0]);
$foundMethodCall = true; $foundMethodCall = true;
@ -72,11 +72,11 @@ class NelmioApiDocExtensionTest extends TestCase
$this->assertEquals([ $this->assertEquals([
'Foo1' => [ 'Foo1' => [
'type' => 'App\\Bar', 'type' => 'App\\Bar',
'groups' => [], 'groups' => null,
], ],
'Test1' => [ 'Test1' => [
'type' => 'App\\Test', 'type' => 'App\\Test',
'groups' => [], 'groups' => null,
], ],
], $methodCall[1][0]); ], $methodCall[1][0]);
$foundMethodCall = true; $foundMethodCall = true;

View File

@ -80,7 +80,7 @@ class ModelRegistryTest extends TestCase
], ],
], ],
[ [
'#/definitions/Foo1', '#/definitions/ModelRegistryTest',
null, null,
[ [
'Foo1' => [ 'Foo1' => [
@ -89,6 +89,16 @@ class ModelRegistryTest extends TestCase
], ],
], ],
], ],
[
'#/definitions/Foo1',
[],
[
'Foo1' => [
'type' => self::class,
'groups' => [],
],
],
],
]; ];
} }