From 31ae375ab546b7b1c951c70ca52c2168c8f1f07b Mon Sep 17 00:00:00 2001 From: Guilhem N Date: Sun, 26 Aug 2018 22:15:44 +0200 Subject: [PATCH] Make sure alternative names use the exact names specified (#1384) * Make sure alternative names use the exact name specified * Document the feature * Cs --- DependencyInjection/Configuration.php | 9 +++-- Model/ModelRegistry.php | 37 +++++++------------ Resources/doc/alternative_names.rst | 23 ++++++++++++ .../DependencyInjection/ConfigurationTest.php | 4 +- .../NelmioApiDocExtensionTest.php | 8 ++-- Tests/Model/ModelRegistryTest.php | 12 +++++- 6 files changed, 60 insertions(+), 33 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 83204cc..300643d 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -91,9 +91,12 @@ final class Configuration implements ConfigurationInterface ->children() ->scalarNode('alias')->isRequired()->end() ->scalarNode('type')->isRequired()->end() - ->arrayNode('groups') - ->defaultValue([]) - ->variablePrototype()->end() + ->variableNode('groups') + ->defaultValue(null) + ->validate() + ->ifTrue(function ($v) { return null !== $v && !is_array($v); }) + ->thenInvalid('Model groups must be either `null` or an array.') + ->end() ->end() ->arrayNode('areas') ->defaultValue([]) diff --git a/Model/ModelRegistry.php b/Model/ModelRegistry.php index 1d1a96d..c922741 100644 --- a/Model/ModelRegistry.php +++ b/Model/ModelRegistry.php @@ -41,16 +41,28 @@ final class ModelRegistry $this->modelDescribers = $modelDescribers; $this->api = $api; $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 + { + 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(); if (isset($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->unregistered[] = $hash; @@ -99,7 +111,7 @@ final class ModelRegistry { $definitions = $this->api->getDefinitions(); - $name = $base = $this->getAlternativeName($model) ?? $this->getTypeShortName($model->getType()); + $name = $base = $this->getTypeShortName($model->getType()); $i = 1; while ($definitions->has($name)) { @@ -110,27 +122,6 @@ final class ModelRegistry 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 { if (null !== $type->getCollectionValueType()) { diff --git a/Resources/doc/alternative_names.rst b/Resources/doc/alternative_names.rst index 720b7aa..35b051a 100644 --- a/Resources/doc/alternative_names.rst +++ b/Resources/doc/alternative_names.rst @@ -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_secret`` for the ``private`` area - ``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() + { + } + } diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index a9d609a..d6ac76b 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -92,7 +92,7 @@ class ConfigurationTest extends TestCase [ 'alias' => 'Foo3', 'type' => 'App\Foo', - 'groups' => [], + 'groups' => null, 'areas' => [], ], [ @@ -104,7 +104,7 @@ class ConfigurationTest extends TestCase [ 'alias' => 'Foo1', 'type' => 'App\\Foo', - 'groups' => [], + 'groups' => null, 'areas' => ['internal'], ], [ diff --git a/Tests/DependencyInjection/NelmioApiDocExtensionTest.php b/Tests/DependencyInjection/NelmioApiDocExtensionTest.php index a2b3a25..42cc4ff 100644 --- a/Tests/DependencyInjection/NelmioApiDocExtensionTest.php +++ b/Tests/DependencyInjection/NelmioApiDocExtensionTest.php @@ -53,11 +53,11 @@ class NelmioApiDocExtensionTest extends TestCase $this->assertEquals([ 'Foo1' => [ 'type' => 'App\\Foo', - 'groups' => [], + 'groups' => null, ], 'Test1' => [ 'type' => 'App\\Test', - 'groups' => [], + 'groups' => null, ], ], $methodCall[1][0]); $foundMethodCall = true; @@ -72,11 +72,11 @@ class NelmioApiDocExtensionTest extends TestCase $this->assertEquals([ 'Foo1' => [ 'type' => 'App\\Bar', - 'groups' => [], + 'groups' => null, ], 'Test1' => [ 'type' => 'App\\Test', - 'groups' => [], + 'groups' => null, ], ], $methodCall[1][0]); $foundMethodCall = true; diff --git a/Tests/Model/ModelRegistryTest.php b/Tests/Model/ModelRegistryTest.php index 5f8769c..63d09c3 100644 --- a/Tests/Model/ModelRegistryTest.php +++ b/Tests/Model/ModelRegistryTest.php @@ -80,7 +80,7 @@ class ModelRegistryTest extends TestCase ], ], [ - '#/definitions/Foo1', + '#/definitions/ModelRegistryTest', null, [ 'Foo1' => [ @@ -89,6 +89,16 @@ class ModelRegistryTest extends TestCase ], ], ], + [ + '#/definitions/Foo1', + [], + [ + 'Foo1' => [ + 'type' => self::class, + 'groups' => [], + ], + ], + ], ]; }