Skip to content

Commit 5930f37

Browse files
committed
MC-36456: union implementation
1 parent 2219289 commit 5930f37

File tree

16 files changed

+424
-17
lines changed

16 files changed

+424
-17
lines changed

app/code/Magento/GraphQl/etc/di.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<arguments>
3030
<argument name="factoryMapByConfigElementType" xsi:type="array">
3131
<item name="graphql_interface" xsi:type="object">Magento\Framework\GraphQl\Config\Element\InterfaceFactory</item>
32+
<item name="graphql_union" xsi:type="object">Magento\Framework\GraphQl\Config\Element\UnionFactory</item>
3233
<item name="graphql_type" xsi:type="object">Magento\Framework\GraphQl\Config\Element\TypeFactory</item>
3334
<item name="graphql_input" xsi:type="object">Magento\Framework\GraphQl\Config\Element\InputFactory</item>
3435
<item name="graphql_enum" xsi:type="object">Magento\Framework\GraphQl\Config\Element\EnumFactory</item>
@@ -64,6 +65,7 @@
6465
<item name="Magento\Framework\GraphQl\Config\Element\Type" xsi:type="string">Magento\Framework\GraphQl\Schema\Type\Output\OutputTypeObject</item>
6566
<item name="Magento\Framework\GraphQl\Config\Element\Input" xsi:type="string">Magento\Framework\GraphQl\Schema\Type\Input\InputObjectType</item>
6667
<item name="Magento\Framework\GraphQl\Config\Element\InterfaceType" xsi:type="string">Magento\Framework\GraphQl\Schema\Type\Output\OutputInterfaceObject</item>
68+
<item name="Magento\Framework\GraphQl\Config\Element\UnionType" xsi:type="string">Magento\Framework\GraphQl\Schema\Type\Output\OutputUnionObject</item>
6769
<item name="Magento\Framework\GraphQl\Config\Element\Enum" xsi:type="string">Magento\Framework\GraphQl\Schema\Type\Enum\Enum</item>
6870
</argument>
6971
</arguments>
@@ -78,13 +80,15 @@
7880
<argument name="formatters" xsi:type="array">
7981
<item name="fields" xsi:type="object">Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\Fields</item>
8082
<item name="interfaces" xsi:type="object">Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\Interfaces</item>
83+
<item name="unions" xsi:type="object">Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\Unions</item>
8184
<item name="resolveType" xsi:type="object">Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\ResolveType</item>
8285
</argument>
8386
</arguments>
8487
</type>
8588
<type name="Magento\Framework\GraphQlSchemaStitching\GraphQlReader\TypeReaderComposite">
8689
<arguments>
8790
<argument name="typeReaders" xsi:type="array">
91+
<item name="union_type" xsi:type="object">Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\UnionType</item>
8892
<item name="enum_type" xsi:type="object">Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\EnumType</item>
8993
<item name="object_type" xsi:type="object">Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\ObjectType</item>
9094
<item name="input_object_type" xsi:type="object">Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\InputObjectType</item>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\GraphQl\Config\Element;
9+
10+
use Magento\Framework\GraphQl\Config\ConfigElementFactoryInterface;
11+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
12+
use Magento\Framework\ObjectManagerInterface;
13+
14+
/**
15+
* Factory for config elements of 'union' type.
16+
*/
17+
class UnionFactory implements ConfigElementFactoryInterface
18+
{
19+
/**
20+
* @var ObjectManagerInterface
21+
*/
22+
private $objectManager;
23+
24+
/**
25+
* @param ObjectManagerInterface $objectManager
26+
*/
27+
public function __construct(
28+
ObjectManagerInterface $objectManager
29+
) {
30+
$this->objectManager = $objectManager;
31+
}
32+
33+
/**
34+
* Instantiate an object representing 'interface' GraphQL config element.
35+
*
36+
* @param array $data
37+
* @return ConfigElementInterface
38+
*/
39+
public function createFromConfigData(array $data): ConfigElementInterface
40+
{
41+
return $this->create($data, $data['types'] ?? []);
42+
}
43+
44+
/**
45+
* Create interface object based off array of configured GraphQL Output/InputInterface.
46+
*
47+
* Interface data must contain name, type resolver, and field definitions. The type resolver should point to an
48+
* implementation of the TypeResolverInterface that decides what concrete GraphQL type to output. Description is
49+
* the only optional field.
50+
*
51+
* @param array $unionData
52+
* @param array $types
53+
* @return UnionType
54+
*/
55+
public function create(
56+
array $unionData,
57+
array $types
58+
) : UnionType {
59+
return $this->objectManager->create(
60+
UnionType::class,
61+
[
62+
'name' => $unionData['name'],
63+
'resolver' => $unionData['resolver'],
64+
'types' => $types,
65+
'description' => isset($unionData['description']) ? $unionData['description'] : ''
66+
]
67+
);
68+
}
69+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\GraphQl\Config\Element;
9+
10+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
11+
12+
/**
13+
* Defines contracts for return type data as GraphQL objects.
14+
*/
15+
interface UnionInterface extends ConfigElementInterface
16+
{
17+
/**
18+
* Get a list of fields that make up the possible return or input values of a type.
19+
*
20+
* @return Type[]
21+
*/
22+
public function getTypes() : array;
23+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\GraphQl\Config\Element;
9+
10+
/**
11+
* Class representing 'union' GraphQL config element.
12+
*/
13+
class UnionType implements UnionInterface
14+
{
15+
/**
16+
* @var string
17+
*/
18+
private $name;
19+
20+
/**
21+
* @var string[]
22+
*/
23+
private $types;
24+
25+
/**
26+
* @var string
27+
*/
28+
private $resolver;
29+
30+
/**
31+
* @var string
32+
*/
33+
private $description;
34+
35+
/**
36+
* @param string $name
37+
* @param string $resolver
38+
* @param string[] $types
39+
* @param string $description
40+
*/
41+
public function __construct(
42+
string $name,
43+
string $resolver,
44+
array $types,
45+
string $description
46+
) {
47+
$this->name = $name;
48+
$this->types = $types;
49+
$this->resolver = $resolver;
50+
$this->description = $description;
51+
}
52+
53+
/**
54+
* Get the type name.
55+
*
56+
* @return string
57+
*/
58+
public function getName() : string
59+
{
60+
return $this->name;
61+
}
62+
63+
/**
64+
* Get a list of fields that make up the possible return or input values of a type.
65+
*
66+
* @return string[]
67+
*/
68+
public function getTypes() : array
69+
{
70+
return $this->types;
71+
}
72+
73+
/**
74+
* Return the name of the resolver class that determines the concrete type to display in the result.
75+
*
76+
* @return string
77+
*/
78+
public function getResolver()
79+
{
80+
return $this->resolver;
81+
}
82+
83+
/**
84+
* Get a human-readable description of the type.
85+
*
86+
* @return string
87+
*/
88+
public function getDescription() : string
89+
{
90+
return $this->description;
91+
}
92+
}

lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Fields.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\GraphQl\Config\Data\WrappedTypeProcessor;
1111
use Magento\Framework\GraphQl\Config\Element\Field;
1212
use Magento\Framework\GraphQl\Config\Element\TypeInterface;
13+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
1314
use Magento\Framework\GraphQl\Schema\Type\Input\InputMapper;
1415
use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface;
1516
use Magento\Framework\GraphQl\Schema\Type\Output\OutputMapper;
@@ -89,7 +90,7 @@ public function __construct(
8990
/**
9091
* @inheritdoc
9192
*/
92-
public function format(TypeInterface $configElement, OutputTypeInterface $outputType): array
93+
public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType): array
9394
{
9495
$typeConfig = [
9596
'fields' => function () use ($configElement, $outputType) {

lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Interfaces.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter;
99

1010
use Magento\Framework\GraphQl\Config\Element\Type;
11-
use Magento\Framework\GraphQl\Config\Element\TypeInterface;
11+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
1212
use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface;
1313
use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface;
1414
use Magento\Framework\GraphQl\Schema\Type\Output\OutputMapper;
@@ -34,7 +34,7 @@ public function __construct(OutputMapper $outputMapper)
3434
/**
3535
* {@inheritDoc}
3636
*/
37-
public function format(TypeInterface $configElement, OutputTypeInterface $outputType) : array
37+
public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array
3838
{
3939
$config = [];
4040
if ($configElement instanceof Type && !empty($configElement->getInterfaces())) {

lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/ResolveType.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter;
99

1010
use Magento\Framework\GraphQl\Config\Element\InterfaceType;
11-
use Magento\Framework\GraphQl\Config\Element\TypeInterface;
11+
use Magento\Framework\GraphQl\Config\Element\UnionType;
12+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
1213
use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface;
1314
use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface;
1415
use Magento\Framework\ObjectManagerInterface;
@@ -34,14 +35,19 @@ public function __construct(ObjectManagerInterface $objectManager)
3435
/**
3536
* {@inheritDoc}
3637
*/
37-
public function format(TypeInterface $configElement, OutputTypeInterface $outputType) : array
38+
public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array
3839
{
3940
$config = [];
4041
if ($configElement instanceof InterfaceType) {
4142
$typeResolver = $this->objectManager->create($configElement->getTypeResolver());
4243
$config['resolveType'] = function ($value) use ($typeResolver) {
4344
return $typeResolver->resolveType($value);
4445
};
46+
} elseif ($configElement instanceof UnionType) {
47+
$typeResolver = $this->objectManager->create($configElement->getResolver());
48+
$config['resolveType'] = function ($value) use ($typeResolver) {
49+
return $typeResolver->resolveType($value);
50+
};
4551
}
4652

4753
return $config;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter;
9+
10+
use Magento\Framework\GraphQl\Config\Element\UnionType;
11+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
12+
use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface;
13+
use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\Output\OutputMapper;
15+
16+
/**
17+
* Add unions implemented by type if configured.
18+
*/
19+
class Unions implements FormatterInterface
20+
{
21+
/**
22+
* @var OutputMapper
23+
*/
24+
private $outputMapper;
25+
26+
/**
27+
* @param OutputMapper $outputMapper
28+
*/
29+
public function __construct(OutputMapper $outputMapper)
30+
{
31+
$this->outputMapper = $outputMapper;
32+
}
33+
34+
/**
35+
* {@inheritDoc}
36+
*/
37+
public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array
38+
{
39+
$config = [];
40+
if ($configElement instanceof UnionType && !empty($configElement->getTypes())) {
41+
$unionTypes = [];
42+
foreach ($configElement->getTypes() as $unionName) {
43+
$unionTypes[$unionName] = $this->outputMapper->getOutputType($unionName);
44+
}
45+
$config['types'] = $unionTypes;
46+
}
47+
48+
return $config;
49+
}
50+
}

lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterComposite.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper;
99

10-
use Magento\Framework\GraphQl\Config\Element\TypeInterface;
10+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
1111
use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface;
1212

1313
/**
@@ -31,7 +31,7 @@ public function __construct(array $formatters)
3131
/**
3232
* {@inheritDoc}
3333
*/
34-
public function format(TypeInterface $configElement, OutputTypeInterface $outputType) : array
34+
public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array
3535
{
3636
$config = [
3737
'name' => $configElement->getName(),

lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterInterface.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper;
99

10-
use Magento\Framework\GraphQl\Config\Element\TypeInterface as TypeElementInterface;
10+
use Magento\Framework\GraphQl\Config\ConfigElementInterface;
1111
use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface;
1212

1313
/**
@@ -18,9 +18,9 @@ interface FormatterInterface
1818
/**
1919
* Convert GraphQL config element to the object compatible with GraphQL schema generator.
2020
*
21-
* @param TypeElementInterface $configElement
21+
* @param ConfigElementInterface $configElement
2222
* @param OutputTypeInterface $outputType
2323
* @return array
2424
*/
25-
public function format(TypeElementInterface $configElement, OutputTypeInterface $outputType) : array;
25+
public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array;
2626
}

0 commit comments

Comments
 (0)