diff --git a/src/Context.php b/src/Context.php new file mode 100644 index 0000000000000000000000000000000000000000..eeb6c3015c613b66dfbc962c3d2bc727f5dd1435 --- /dev/null +++ b/src/Context.php @@ -0,0 +1,128 @@ +<?php declare(strict_types=1); +/* + * irstea/ng-model-generator-bundle generates Typescript interfaces for Angular using api-platform metadata. + * Copyright (C) 2018 IRSTEA + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License and the GNU + * Lesser General Public License along with this program. If not, see + * <https://www.gnu.org/licenses/>. + */ + +namespace Irstea\NgModelGeneratorBundle; + +/** + * Class Context. + */ +class Context implements ContextInterface +{ + /** @var string */ + private $rootClass; + + /** @var bool */ + private $normalization; + + /** @var string[] */ + private $groups; + + /** @var string[][] */ + private $defaultGroups; + + /** + * Context constructor. + * + * @param string $rootClass + * @param bool $normalization + * @param string[] $groups + * @param \string[][] $defaultGroups + */ + public function __construct(string $rootClass, array $defaultGroups, bool $normalization = false, array $groups = []) + { + $this->rootClass = $rootClass; + $this->defaultGroups = $defaultGroups; + $this->normalization = $normalization; + $this->groups = $groups; + sort($this->groups); + } + + /** + * @param bool $normalization + * + * @return Context + */ + public function withNormalization(bool $normalization): ContextInterface + { + if ($normalization === $this->normalization) { + return $this; + } + + $clone = clone $this; + $clone->normalization = $normalization; + + return $clone; + } + + /** + * @param bool $normalization + * + * @return Context + */ + public function withGroups(array $groups): ContextInterface + { + sort($groups); + + /* @noinspection TypeUnsafeComparisonInspection */ + if ($groups == $this->groups) { + return $this; + } + + $clone = clone $this; + $clone->groups = $groups; + + return $clone; + } + + /** + * Get rootClass. + * + * @return string + */ + public function getRootClass(): string + { + return $this->rootClass; + } + + /** + * @return bool + */ + public function isNormalization(): bool + { + return $this->normalization; + } + + /** + * @return array + */ + public function getGroups(): array + { + return $this->groups; + } + + /** + * @param string $className + * + * @return string[] + */ + public function getDefaultGroups(string $className): array + { + return $this->defaultGroups[$this->normalization ? 'normalization' : 'denormalization'][$className] ?? []; + } +} diff --git a/src/ContextInterface.php b/src/ContextInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d03fdf91d82298f67f1c5ac8f7b6c86bd0becf37 --- /dev/null +++ b/src/ContextInterface.php @@ -0,0 +1,64 @@ +<?php declare(strict_types=1); +/* + * irstea/ng-model-generator-bundle generates Typescript interfaces for Angular using api-platform metadata. + * Copyright (C) 2018 IRSTEA + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License and the GNU + * Lesser General Public License along with this program. If not, see + * <https://www.gnu.org/licenses/>. + */ + +namespace Irstea\NgModelGeneratorBundle; + +/** + * Interface ContextInterface. + */ +interface ContextInterface +{ + /** + * @param bool $normalization + * + * @return Context + */ + public function withNormalization(bool $normalization): self; + + /** + * @param bool $normalization + * + * @return Context + */ + public function withGroups(array $groups): self; + + /** + * Get rootClass. + * + * @return string + */ + public function getRootClass(): string; + + /** + * @return bool + */ + public function isNormalization(): bool; + + /** + * @return array + */ + public function getGroups(): array; + + /** + * @param string $className + * + * @return string[] + */ + public function getDefaultGroups(string $className): array; +} diff --git a/src/DefaultNamingStrategy.php b/src/DefaultNamingStrategy.php new file mode 100644 index 0000000000000000000000000000000000000000..5f7ec0e802d7e27e49ed34e274ec9eea241bacec --- /dev/null +++ b/src/DefaultNamingStrategy.php @@ -0,0 +1,62 @@ +<?php declare(strict_types=1); +/* + * irstea/ng-model-generator-bundle generates Typescript interfaces for Angular using api-platform metadata. + * Copyright (C) 2018 IRSTEA + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License and the GNU + * Lesser General Public License along with this program. If not, see + * <https://www.gnu.org/licenses/>. + */ + +namespace Irstea\NgModelGeneratorBundle; + +/** + * Class DefaultNamingStrategy. + */ +final class DefaultNamingStrategy implements NamingStrategy +{ + /** + * {@inheritdoc} + */ + public function getName(ContextInterface $ctx, string $resourceClass): string + { + $parts = array_diff( + $ctx->getGroups(), + $ctx->getDefaultGroups($resourceClass), + $ctx->getDefaultGroups($ctx->getRootClass()) + ); + + $baseName = FQCN::baseName($resourceClass); + $shortPrefix = $ctx->isNormalization() ? '' : 'Put'; + $fullPrefix = $ctx->isNormalization() ? 'Get' : 'Put'; + + if ($resourceClass === $ctx->getRootClass()) { + if (\in_array($shortPrefix . $baseName, $parts, true)) { + array_unshift($parts, $baseName); + } else { + array_unshift($parts, $shortPrefix . $baseName); + } + } else { + $rootBaseName = FQCN::baseName($ctx->getRootClass()); + $rootGroup = $fullPrefix . $rootBaseName; + if (\in_array($rootGroup, $parts, true)) { + array_unshift($parts, $rootBaseName); + } else { + array_unshift($parts, $rootGroup); + } + + $parts[] = $baseName; + } + + return implode('', $parts); + } +} diff --git a/src/ModelGenerator.php b/src/ModelGenerator.php index 81b94ebdaa9a9d90f670573340591972ee54dd41..294272d427d27e87d0cbba1ce40bbdc5c326cb60 100644 --- a/src/ModelGenerator.php +++ b/src/ModelGenerator.php @@ -34,14 +34,13 @@ use Irstea\NgModelGeneratorBundle\Models\Types\Reference; use Irstea\NgModelGeneratorBundle\Models\Types\Repository; use Irstea\NgModelGeneratorBundle\Models\Types\Representation; use Irstea\NgModelGeneratorBundle\Models\Types\Type; -use Irstea\NgModelGeneratorBundle\Models\Types\TypeFactoryInterface; use Symfony\Component\PropertyInfo\Type as PHPType; use Twig\Environment; /** * Class Serializer. */ -final class ModelGenerator implements ResourceTypeFactoryFactory +final class ModelGenerator { /** @var MetadataFactoryInterface */ private $metadataFactory; @@ -137,9 +136,9 @@ final class ModelGenerator implements ResourceTypeFactoryFactory /** * Crée une usine à types contenant un certain nombre de types par défaut. * - * @return TypeFactory + * @return TypeFactoryInterface */ - private function createTypeFactory(): TypeFactory + private function createTypeFactory(): TypeFactoryInterface { $factory = new TypeFactory(); @@ -181,7 +180,11 @@ final class ModelGenerator implements ResourceTypeFactoryFactory $factory->addAlias($alias, $target); } - return $factory; + return new ResourceTypeFactory( + $this->metadataFactory, + $factory, + new DefaultNamingStrategy() + ); } /** @@ -238,39 +241,27 @@ final class ModelGenerator implements ResourceTypeFactoryFactory /** @var string $className */ foreach ($this->getResourceMetadata() as $className => $resourceMeta) { - $resources[$className] = []; + $representations[$className] = []; foreach (['normalization', 'denormalization'] as $normalization) { - $representations[$className][$normalization] = $this - ->createResourceTypeFactory( - $this->defaultGroups[$normalization][$className], - $normalization === 'normalization' - ) - ->get($className) - ->dereference(); + $ctx = new Context( + $className, + $this->defaultGroups, + $normalization === 'normalization', + $this->defaultGroups[$normalization][$className] + ); + + $representations[$className][$normalization] = + $this->typeFactory + ->withContext($ctx) + ->get($className) + ->dereference(); } } return $representations; } - /** - * @param $groups - * @param $normalization - * - * @return TypeFactoryInterface - */ - public function createResourceTypeFactory(array $groups, bool $normalization): TypeFactoryInterface - { - return new ResourceTypeFactory( - $this->metadataFactory, - $this->typeFactory, - $groups, - $normalization, - $this->defaultGroups[$normalization ? 'normalization' : 'denormalization'] ?? [] - ); - } - /** * @return array */ @@ -282,18 +273,20 @@ final class ModelGenerator implements ResourceTypeFactoryFactory foreach ($this->getResourceMetadata() as $className => $resourceMeta) { $repoName = $resourceMeta->getShortName() . 'Repository'; + $ctx = new Context($className, $this->defaultGroups); + $repositories[$repoName] = $this->typeFactory->getOrCreate( $repoName, - function () use ($resourceMeta, $className, &$iriPatterns): Type { + function () use ($resourceMeta, $className, &$iriPatterns, $ctx): Type { $operations = []; foreach ($resourceMeta->getOperations() as $operation) { $mapper = new OperationMapper( - $this, - $this->typeFactory, + $this->typeFactory->withContext($ctx), $operation, - $this->resources[$className]['normalization'] + $this->resources[$className]['normalization'], + $ctx ); $operations[] = $operation = $mapper(); diff --git a/src/ResourceTypeFactoryFactory.php b/src/NamingStrategy.php similarity index 73% rename from src/ResourceTypeFactoryFactory.php rename to src/NamingStrategy.php index cae52adc9fbc66cfa4c74a7970f66cddd6f8b718..e5184a7d84ca02763f491446ce0db682af3db9a2 100644 --- a/src/ResourceTypeFactoryFactory.php +++ b/src/NamingStrategy.php @@ -19,18 +19,16 @@ namespace Irstea\NgModelGeneratorBundle; -use Irstea\NgModelGeneratorBundle\Models\Types\TypeFactoryInterface; - /** - * Class ResourceTypeFactoryFactory. + * Interface NamingStrategy. */ -interface ResourceTypeFactoryFactory +interface NamingStrategy { /** - * @param array $groups - * @param bool $normalization + * @param ContextInterface $context + * @param string $resourceClass * - * @return TypeFactoryInterface + * @return mixed */ - public function createResourceTypeFactory(array $groups, bool $normalization): TypeFactoryInterface; + public function getName(ContextInterface $context, string $resourceClass); } diff --git a/src/OperationMapper.php b/src/OperationMapper.php index 15a246d2f429fc64acac2d4be1e50ec863f2cb39..a2483f57b2a0d78995cc1ae48cfb82560ef4ad78 100644 --- a/src/OperationMapper.php +++ b/src/OperationMapper.php @@ -34,7 +34,6 @@ use Irstea\NgModelGeneratorBundle\Models\Types\ObjectClass; use Irstea\NgModelGeneratorBundle\Models\Types\Property; use Irstea\NgModelGeneratorBundle\Models\Types\Representation; use Irstea\NgModelGeneratorBundle\Models\Types\Type; -use Irstea\NgModelGeneratorBundle\Models\Types\TypeFactoryInterface; use Irstea\NgModelGeneratorBundle\Models\Types\Union; use Symfony\Component\PropertyInfo\Type as APIType; @@ -58,9 +57,6 @@ final class OperationMapper 'post' => 'post(%s)', ]; - /** @var ResourceTypeFactoryFactory */ - private $resourceTypeFactoryFactory; - /** @var TypeFactoryInterface */ private $typeFactory; @@ -70,20 +66,23 @@ final class OperationMapper /** @var Representation */ private $baseRepr; + /** @var ContextInterface */ + private $context; + /** * OperationMapper constructor. * - * @param ResourceTypeFactoryFactory $resourceTypeFactoryFactory - * @param TypeFactoryInterface $typeFactory - * @param OperationMetadata $operation - * @param Representation $baseRepr + * @param TypeFactoryInterface $typeFactory + * @param OperationMetadata $operation + * @param Representation $baseRepr + * @param ContextInterface $context */ - public function __construct(ResourceTypeFactoryFactory $resourceTypeFactoryFactory, TypeFactoryInterface $typeFactory, OperationMetadata $operation, Representation $baseRepr) + public function __construct(TypeFactoryInterface $typeFactory, OperationMetadata $operation, Representation $baseRepr, ContextInterface $context) { - $this->resourceTypeFactoryFactory = $resourceTypeFactoryFactory; $this->typeFactory = $typeFactory; $this->operation = $operation; $this->baseRepr = $baseRepr; + $this->context = $context; } /** @@ -102,20 +101,22 @@ final class OperationMapper $requestBody = $responseBody = $queryParameters = null; if ($denormalize) { - $requestBody = $this->resourceTypeFactoryFactory - ->createResourceTypeFactory( - $this->operation->getAttribute('denormalization_groups'), - false + $requestBody = $this->typeFactory + ->withContext( + $this->context + ->withNormalization(false) + ->withGroups($this->operation->getAttribute('denormalization_groups')) ) ->get($className) ->dereference(); } if ($normalize) { - $responseBody = $this->resourceTypeFactoryFactory - ->createResourceTypeFactory( - $this->operation->getAttribute('normalization_groups'), - true + $responseBody = $this->typeFactory + ->withContext( + $this->context + ->withNormalization(true) + ->withGroups($this->operation->getAttribute('normalization_groups')) ) ->get($className) ->dereference(); diff --git a/src/ResourceTypeFactory.php b/src/ResourceTypeFactory.php index 4123b22e7bd1da6cd1b09fffd18433d991411649..b4c0064bc0907b3a72270dcae3adcdeb4f71aac4 100644 --- a/src/ResourceTypeFactory.php +++ b/src/ResourceTypeFactory.php @@ -24,13 +24,10 @@ use Irstea\NgModelGeneratorBundle\Models\Metadata\PropertyMetadata; use Irstea\NgModelGeneratorBundle\Models\Types\BuiltinType; use Irstea\NgModelGeneratorBundle\Models\Types\Collection; use Irstea\NgModelGeneratorBundle\Models\Types\GenericRef; -use Irstea\NgModelGeneratorBundle\Models\Types\Placeholder; use Irstea\NgModelGeneratorBundle\Models\Types\Property; use Irstea\NgModelGeneratorBundle\Models\Types\Representation; use Irstea\NgModelGeneratorBundle\Models\Types\StringConst; use Irstea\NgModelGeneratorBundle\Models\Types\Type; -use Irstea\NgModelGeneratorBundle\Models\Types\TypeFactoryInterface; -use Irstea\NgModelGeneratorBundle\Models\Types\Union; /** * Class TypeMapper. @@ -43,38 +40,48 @@ final class ResourceTypeFactory implements TypeFactoryInterface /** @var TypeFactoryInterface */ private $typeFactory; - /** @var string[] */ - private $groups; + /** @var NamingStrategy */ + private $namingStrategy; - /** @var bool */ - private $normalization; - - /** @var string[][] */ - private $defaultGroups; + /** @var ContextInterface|null */ + private $context; /** * TypeMapper constructor. * * @param MetadataFactoryInterface $metadataFactory * @param TypeFactoryInterface $typeFactory - * @param string[] $groups - * @param bool $normalization - * @param array $defaultGroups + * @param NamingStrategy $namingStrategy + * @param ContextInterface $context */ public function __construct( MetadataFactoryInterface $metadataFactory, TypeFactoryInterface $typeFactory, - array $groups, - bool $normalization, - array $defaultGroups + NamingStrategy $namingStrategy, + ContextInterface $context = null ) { $this->metadataFactory = $metadataFactory; $this->typeFactory = $typeFactory; - $this->groups = $groups; - $this->normalization = $normalization; - $this->defaultGroups = $defaultGroups; + $this->namingStrategy = $namingStrategy; + $this->context = $context; + } - sort($this->groups); + /** + * @param ContextInterface|null $context + * + * @return TypeFactoryInterface + */ + public function withContext(?ContextInterface $context): TypeFactoryInterface + { + if ($context === $this->context) { + return $this; + } + + $clone = clone $this; + $clone->context = $context; + $clone->typeFactory = $clone->typeFactory->withContext($context); + + return $clone; } /** @@ -98,12 +105,12 @@ final class ResourceTypeFactory implements TypeFactoryInterface */ public function get(string $name): Type { - if (!class_exists($name) || $this->typeFactory->has($name)) { + if (!$this->context || !class_exists($name) || $this->typeFactory->has($name)) { return $this->typeFactory->get($name); } if ($this->metadataFactory->isResource($name)) { - $reprName = $this->getRepresentationName($name); + $reprName = $this->namingStrategy->getName($this->context, $name); return $this->typeFactory->getOrCreate( $reprName, @@ -140,26 +147,6 @@ final class ResourceTypeFactory implements TypeFactoryInterface return $this->typeFactory->getGenericRef($defName, $parameters); } - /** - * @param string $resourceFQCN - * - * @return string - */ - private function getRepresentationName(string $resourceFQCN): string - { - $name = FQCN::baseName($resourceFQCN); - - if ($this->groups != $this->defaultGroups[$resourceFQCN]) { - $name .= implode('', $this->groups); - } - - if (!$this->normalization && strpos($name, 'Put') === false) { - $name = 'Put' . $name; - } - - return $name; - } - /** * @param string $name * @param string $resourceClass @@ -170,22 +157,30 @@ final class ResourceTypeFactory implements TypeFactoryInterface { $resourceMeta = $this->metadataFactory->getResourceMetadata($resourceClass); - $propertiesMeta = $resourceMeta->getProperties($this->groups); + $normalization = $this->context->isNormalization(); + $groups = $this->context->getGroups(); + + $propertiesMeta = $resourceMeta->getProperties($groups); $properties = $this->mapProperties($propertiesMeta); $parents = []; - if ($this->normalization) { + if ($normalization) { $shortName = $resourceMeta->getShortName(); - $properties['@id'] = Property::createIdentifier('@id', 'JSON-LD identifier', $this->typeFactory->getGenericRef('IRI<T>', [BuiltinType::get($shortName)])); + $properties['@id'] = Property::createIdentifier( + '@id', + 'JSON-LD identifier', + $this->typeFactory->getGenericRef('IRI<T>', [BuiltinType::get($shortName)]) + ); $properties['@type'] = Property::createIdentifier('@type', 'JSON-LD type', StringConst::get($shortName)); } $desc = [$resourceMeta->getDescription()]; - $desc[] = 'Direction: ' . ($this->normalization ? 'response' : 'request'); - $desc[] = sprintf('Serialization groups: %s', $this->groups ? implode(', ', $this->groups) : '-'); + $desc[] = 'Resource: ' . $resourceClass; + $desc[] = 'Direction: ' . ($normalization ? 'response' : 'request'); + $desc[] = sprintf('Serialization groups: %s', $groups ? implode(', ', $groups) : '-'); return new Representation($resourceClass, $name, $parents, $properties, trim(implode("\n", $desc))); } @@ -236,7 +231,7 @@ final class ResourceTypeFactory implements TypeFactoryInterface */ private function acceptProperty(PropertyMetadata $propertyMeta): bool { - return $this->normalization ? $propertyMeta->isReadable() : $propertyMeta->isWritable(); + return $this->context->isNormalization() ? $propertyMeta->isReadable() : $propertyMeta->isWritable(); } /** diff --git a/src/TypeFactory.php b/src/TypeFactory.php index 12afde8a7d4560aa820faa56b4ecabab1a302943..7b8036091934649c5066fb2777e0d1e73e1f1a80 100644 --- a/src/TypeFactory.php +++ b/src/TypeFactory.php @@ -26,17 +26,23 @@ use Irstea\NgModelGeneratorBundle\Models\Types\GenericDef; use Irstea\NgModelGeneratorBundle\Models\Types\GenericRef; use Irstea\NgModelGeneratorBundle\Models\Types\Reference; use Irstea\NgModelGeneratorBundle\Models\Types\Type; -use Irstea\NgModelGeneratorBundle\Models\Types\TypeFactoryInterface; /** * Class TypeFactory. */ final class TypeFactory implements TypeFactoryInterface, \IteratorAggregate { + /** @var Type[] */ + private $types = []; + /** - * @var array<string,Type> + * {@inheritdoc} */ - private $types = []; + public function withContext(?ContextInterface $context): TypeFactoryInterface + { + // On utilise pas le contexte dans cette classe, donc en changer ne change rien. + return $this; + } /** * {@inheritdoc} diff --git a/src/Models/Types/TypeFactoryInterface.php b/src/TypeFactoryInterface.php similarity index 85% rename from src/Models/Types/TypeFactoryInterface.php rename to src/TypeFactoryInterface.php index 01a122ff92e4ffb35d0a316f07a0d2cf013947a5..ba77323c55e11f1ac91b716ab4854decedf0b1e1 100644 --- a/src/Models/Types/TypeFactoryInterface.php +++ b/src/TypeFactoryInterface.php @@ -17,13 +17,23 @@ * <https://www.gnu.org/licenses/>. */ -namespace Irstea\NgModelGeneratorBundle\Models\Types; +namespace Irstea\NgModelGeneratorBundle; + +use Irstea\NgModelGeneratorBundle\Models\Types\GenericRef; +use Irstea\NgModelGeneratorBundle\Models\Types\Type; /** * Interface TypeFactoryInterface. */ interface TypeFactoryInterface { + /** + * @param ContextInterface|null $context + * + * @return TypeFactoryInterface + */ + public function withContext(?ContextInterface $context): self; + /** * @param string $name * diff --git a/tests/DefaultNamingStrategyTest.php b/tests/DefaultNamingStrategyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d71c35ecc9e25df07451b36ff29f0470088094c7 --- /dev/null +++ b/tests/DefaultNamingStrategyTest.php @@ -0,0 +1,88 @@ +<?php declare(strict_types=1); +/* + * irstea/ng-model-generator-bundle generates Typescript interfaces for Angular using api-platform metadata. + * Copyright (C) 2018 IRSTEA + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License and the GNU + * Lesser General Public License along with this program. If not, see + * <https://www.gnu.org/licenses/>. + */ + +namespace Irstea\NgModelGeneratorBundle\Tests; + +use Irstea\NgModelGeneratorBundle\ContextInterface; +use Irstea\NgModelGeneratorBundle\DefaultNamingStrategy; +use PHPUnit\Framework\TestCase; +use Prophecy\Argument; +use Prophecy\Prophecy\ObjectProphecy; + +/** + * Class DefaultNamingStrategyTest. + */ +class DefaultNamingStrategyTest extends TestCase +{ + /** + * @dataProvider getNameTestCaseProvider + */ + public function testGetName(string $expected, string $resourceClass, string $rootClass, bool $normalization, array $groups, array $defaultGroups) + { + /** @var ObjectProphecy|ContextInterface $ctx */ + $ctx = $this->prophesize(ContextInterface::class); + $ctx->getRootClass()->willReturn($rootClass); + $ctx->isNormalization()->willReturn($normalization); + $ctx->getGroups()->willReturn($groups); + $ctx->getDefaultGroups(Argument::type('string'))->will(function ($args) use ($defaultGroups) { + return $defaultGroups[$args[0]] ?? []; + }); + + $strategy = new DefaultNamingStrategy(); + + $actual = $strategy->getName($ctx->reveal(), $resourceClass); + + self::assertEquals($expected, $actual); + } + + /** + * @return array + */ + public function getNameTestCaseProvider(): array + { + return [ + // expected resource root norm? groups? defaultGroups ? + ['Bar', '\\App\\Bar', '\\App\\Bar', true, [], []], + ['BarGetBar', '\\App\\Bar', '\\App\\Bar', true, ['GetBar'], []], + ['Bar', '\\App\\Bar', '\\App\\Bar', true, ['GetBar'], ['\\App\\Bar' => ['GetBar']]], + ['BarGetQuz', '\\App\\Bar', '\\App\\Bar', true, ['GetQuz'], []], + + ['PutBar', '\\App\\Bar', '\\App\\Bar', false, [], []], + ['BarPutBar', '\\App\\Bar', '\\App\\Bar', false, ['PutBar'], []], + ['PutBar', '\\App\\Bar', '\\App\\Bar', false, ['PutBar'], ['\\App\\Bar' => ['PutBar']]], + ['PutBarPutQuz', '\\App\\Bar', '\\App\\Bar', false, ['PutQuz'], []], + + ['GetBarFoo', '\\App\\Foo', '\\App\\Bar', true, [], []], + ['BarGetBarFoo', '\\App\\Foo', '\\App\\Bar', true, ['GetBar'], []], + ['GetBarFoo', '\\App\\Foo', '\\App\\Bar', true, ['GetBar'], ['\\App\\Bar' => ['GetBar']]], + ['GetBarGetFooFoo', '\\App\\Foo', '\\App\\Bar', true, ['GetFoo'], []], + ['GetBarGetFooFoo', '\\App\\Foo', '\\App\\Bar', true, ['GetFoo', 'GetBar'], ['\\App\\Bar' => ['GetBar']]], + ['GetBarFoo', '\\App\\Foo', '\\App\\Bar', true, ['GetFoo'], ['\\App\\Foo' => ['GetFoo']]], + ['GetBarGetQuzFoo', '\\App\\Foo', '\\App\\Bar', true, ['GetQuz'], []], + + ['PutBarFoo', '\\App\\Foo', '\\App\\Bar', false, [], []], + ['BarPutBarFoo', '\\App\\Foo', '\\App\\Bar', false, ['PutBar'], []], + ['PutBarFoo', '\\App\\Foo', '\\App\\Bar', false, ['PutBar'], ['\\App\\Bar' => ['PutBar']]], + ['PutBarPutFooFoo', '\\App\\Foo', '\\App\\Bar', false, ['PutFoo'], []], + ['PutBarPutFooFoo', '\\App\\Foo', '\\App\\Bar', false, ['PutFoo', 'PutBar'], ['\\App\\Bar' => ['PutBar']]], + ['PutBarFoo', '\\App\\Foo', '\\App\\Bar', false, ['PutFoo'], ['\\App\\Foo' => ['PutFoo']]], + ['PutBarPutQuzFoo', '\\App\\Foo', '\\App\\Bar', false, ['PutQuz'], []], + ]; + } +}