Skip to content

Commit 4fdca6e

Browse files
authored
Determine union type name via naming strategy (#530)
Co-authored-by: Malte Dölker <malte@pirateship.com>
1 parent 29c03af commit 4fdca6e

10 files changed

Lines changed: 58 additions & 12 deletions

src/Mappers/Root/CompoundTypeMapper.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use RuntimeException;
2424
use TheCodingMachine\GraphQLite\Mappers\CannotMapTypeException;
2525
use TheCodingMachine\GraphQLite\Mappers\RecursiveTypeMapperInterface;
26+
use TheCodingMachine\GraphQLite\NamingStrategyInterface;
2627
use TheCodingMachine\GraphQLite\TypeRegistry;
2728
use TheCodingMachine\GraphQLite\Types\UnionType;
2829

@@ -38,8 +39,13 @@
3839
*/
3940
class CompoundTypeMapper implements RootTypeMapperInterface
4041
{
41-
public function __construct(private RootTypeMapperInterface $next, private RootTypeMapperInterface $topRootTypeMapper, private TypeRegistry $typeRegistry, private RecursiveTypeMapperInterface $recursiveTypeMapper)
42-
{
42+
public function __construct(
43+
private RootTypeMapperInterface $next,
44+
private RootTypeMapperInterface $topRootTypeMapper,
45+
private NamingStrategyInterface $namingStrategy,
46+
private TypeRegistry $typeRegistry,
47+
private RecursiveTypeMapperInterface $recursiveTypeMapper,
48+
) {
4349
}
4450

4551
public function toGraphQLOutputType(Type $type, OutputType|null $subType, ReflectionMethod|ReflectionProperty $reflector, DocBlock $docBlockObj): OutputType
@@ -144,7 +150,7 @@ private function getTypeFromUnion(array $unionTypes): GraphQLType
144150
throw CannotMapTypeException::createForBadTypeInUnion($unionTypes);
145151
}
146152

147-
$graphQlType = new UnionType($nonNullableUnionTypes, $this->recursiveTypeMapper);
153+
$graphQlType = new UnionType($nonNullableUnionTypes, $this->recursiveTypeMapper, $this->namingStrategy);
148154
$graphQlType = $this->typeRegistry->getOrRegisterType($graphQlType);
149155
assert($graphQlType instanceof UnionType);
150156
}

src/NamingStrategy.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use TheCodingMachine\GraphQLite\Annotations\Input;
99
use TheCodingMachine\GraphQLite\Annotations\TypeInterface;
1010

11+
use function implode;
1112
use function lcfirst;
1213
use function str_ends_with;
1314
use function str_replace;
@@ -109,4 +110,14 @@ public function getInputFieldNameFromMethodName(string $methodName): string
109110

110111
return $methodName;
111112
}
113+
114+
/**
115+
* Returns the name of a GraphQL union type based on the included types.
116+
*
117+
* @param string[] $typeNames The list of GraphQL type names
118+
*/
119+
public function getUnionTypeName(array $typeNames): string
120+
{
121+
return 'Union' . implode('', $typeNames);
122+
}
112123
}

src/NamingStrategyInterface.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ public function getFieldNameFromMethodName(string $methodName): string;
4444
* Returns the name of a GraphQL input field from the name of the annotated method.
4545
*/
4646
public function getInputFieldNameFromMethodName(string $methodName): string;
47+
48+
/**
49+
* Returns the name of a GraphQL union type based on the included types.
50+
*
51+
* @param string[] $typeNames The list of GraphQL type names
52+
*/
53+
public function getUnionTypeName(array $typeNames): string;
4754
}

src/SchemaFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ public function createSchema(): Schema
407407
}
408408
}
409409

410-
$rootTypeMapper = new CompoundTypeMapper($rootTypeMapper, $topRootTypeMapper, $typeRegistry, $recursiveTypeMapper);
410+
$rootTypeMapper = new CompoundTypeMapper($rootTypeMapper, $topRootTypeMapper, $namingStrategy, $typeRegistry, $recursiveTypeMapper);
411411
$rootTypeMapper = new IteratorTypeMapper($rootTypeMapper, $topRootTypeMapper);
412412

413413
$topRootTypeMapper->setNext($rootTypeMapper);

src/Types/UnionType.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,31 @@
77
use GraphQL\Type\Definition\ObjectType;
88
use InvalidArgumentException;
99
use TheCodingMachine\GraphQLite\Mappers\RecursiveTypeMapperInterface;
10+
use TheCodingMachine\GraphQLite\NamingStrategyInterface;
1011

12+
use function array_map;
1113
use function gettype;
1214
use function is_object;
1315

1416
class UnionType extends \GraphQL\Type\Definition\UnionType
1517
{
1618
/** @param array<int,ObjectType> $types */
17-
public function __construct(array $types, RecursiveTypeMapperInterface $typeMapper)
19+
public function __construct(
20+
array $types,
21+
RecursiveTypeMapperInterface $typeMapper,
22+
NamingStrategyInterface $namingStrategy,
23+
)
1824
{
19-
$name = 'Union';
25+
// Make sure all types are object types
2026
foreach ($types as $type) {
21-
$name .= $type->name;
2227
if (! $type instanceof ObjectType) {
2328
throw InvalidTypesInUnionException::notObjectType();
2429
}
2530
}
31+
32+
$typeNames = array_map(static fn (ObjectType $type) => $type->name, $types);
33+
$name = $namingStrategy->getUnionTypeName($typeNames);
34+
2635
parent::__construct([
2736
'name' => $name,
2837
'types' => $types,

tests/AbstractQueryProviderTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ protected function buildRootTypeMapper(): RootTypeMapperInterface
351351
$rootTypeMapper = new CompoundTypeMapper(
352352
$rootTypeMapper,
353353
$topRootTypeMapper,
354+
new NamingStrategy(),
354355
$this->getTypeRegistry(),
355356
$this->getTypeMapper()
356357
);

tests/Integration/EndToEndTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ public function createContainer(array $overloadedServices = []): ContainerInterf
296296
if (interface_exists(UnitEnum::class)) {
297297
$rootTypeMapper = new EnumTypeMapper($rootTypeMapper, $container->get(AnnotationReader::class), new ArrayAdapter(), [ $container->get(NamespaceFactory::class)->createNamespace('TheCodingMachine\\GraphQLite\\Fixtures81\\Integration\\Models') ]);
298298
}
299-
$rootTypeMapper = new CompoundTypeMapper($rootTypeMapper, $container->get(RootTypeMapperInterface::class), $container->get(TypeRegistry::class), $container->get(RecursiveTypeMapperInterface::class));
299+
$rootTypeMapper = new CompoundTypeMapper($rootTypeMapper, $container->get(RootTypeMapperInterface::class), $container->get(NamingStrategyInterface::class), $container->get(TypeRegistry::class), $container->get(RecursiveTypeMapperInterface::class));
300300
$rootTypeMapper = new IteratorTypeMapper($rootTypeMapper, $container->get(RootTypeMapperInterface::class));
301301
return $rootTypeMapper;
302302
},

tests/Mappers/Root/CompoundTypeMapperTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use RuntimeException;
1212
use TheCodingMachine\GraphQLite\AbstractQueryProviderTest;
1313
use TheCodingMachine\GraphQLite\Mappers\CannotMapTypeException;
14+
use TheCodingMachine\GraphQLite\NamingStrategy;
1415

1516
class CompoundTypeMapperTest extends AbstractQueryProviderTest
1617
{
@@ -19,6 +20,7 @@ public function testException1()
1920
$compoundTypeMapper = new CompoundTypeMapper(
2021
new FinalRootTypeMapper($this->getTypeMapper()),
2122
new FinalRootTypeMapper($this->getTypeMapper()),
23+
new NamingStrategy(),
2224
$this->getTypeRegistry(),
2325
$this->getTypeMapper()
2426
);
@@ -32,6 +34,7 @@ public function testException2()
3234
$compoundTypeMapper = new CompoundTypeMapper(
3335
new FinalRootTypeMapper($this->getTypeMapper()),
3436
new FinalRootTypeMapper($this->getTypeMapper()),
37+
new NamingStrategy(),
3538
$this->getTypeRegistry(),
3639
$this->getTypeMapper()
3740
);

tests/NamingStrategyTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
class NamingStrategyTest extends TestCase
1111
{
12-
1312
public function testGetInputTypeName(): void
1413
{
1514
$namingStrategy = new NamingStrategy();
@@ -43,4 +42,13 @@ public function testGetFieldNameFromTypeAnnotation(): void
4342
$name = $namingStrategy->getOutputTypeName(TestObject::class, $type);
4443
$this->assertSame('foo', $name);
4544
}
45+
46+
public function testGetUnionTypeName(): void
47+
{
48+
$namingStrategy = new NamingStrategy();
49+
50+
$typeNames = ['Some', 'Arbitrary', 'Type', 'Names'];
51+
$name = $namingStrategy->getUnionTypeName($typeNames);
52+
$this->assertSame('UnionSomeArbitraryTypeNames', $name);
53+
}
4654
}

tests/Types/UnionTypeTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
use TheCodingMachine\GraphQLite\AbstractQueryProviderTest;
99
use TheCodingMachine\GraphQLite\Fixtures\TestObject;
1010
use TheCodingMachine\GraphQLite\Fixtures\TestObject2;
11+
use TheCodingMachine\GraphQLite\NamingStrategy;
1112

1213
class UnionTypeTest extends AbstractQueryProviderTest
1314
{
1415
public function testConstructor(): void
1516
{
16-
$unionType = new UnionType([$this->getTestObjectType(), $this->getTestObjectType2()], $this->getTypeMapper());
17+
$unionType = new UnionType([$this->getTestObjectType(), $this->getTestObjectType2()], $this->getTypeMapper(), new NamingStrategy());
1718
$resolveInfo = $this->getMockBuilder(ResolveInfo::class)->disableOriginalConstructor()->getMock();
1819
$type = $unionType->resolveType(new TestObject('foo'), null, $resolveInfo);
1920
$this->assertSame($this->getTestObjectType(), $type);
@@ -23,7 +24,7 @@ public function testConstructor(): void
2324

2425
public function testException(): void
2526
{
26-
$unionType = new UnionType([$this->getTestObjectType(), $this->getTestObjectType2()], $this->getTypeMapper());
27+
$unionType = new UnionType([$this->getTestObjectType(), $this->getTestObjectType2()], $this->getTypeMapper(), new NamingStrategy());
2728
$this->expectException(\InvalidArgumentException::class);
2829
$resolveInfo = $this->getMockBuilder(ResolveInfo::class)->disableOriginalConstructor()->getMock();
2930
$unionType->resolveType('foo', null, $resolveInfo);
@@ -32,6 +33,6 @@ public function testException(): void
3233
public function testException2(): void
3334
{
3435
$this->expectException(\InvalidArgumentException::class);
35-
new UnionType([new StringType()], $this->getTypeMapper());
36+
new UnionType([new StringType()], $this->getTypeMapper(), new NamingStrategy());
3637
}
3738
}

0 commit comments

Comments
 (0)