diff --git a/app/code/Magento/GraphQl/etc/di.xml b/app/code/Magento/GraphQl/etc/di.xml index fca6c425e2507..d6168cdc37600 100644 --- a/app/code/Magento/GraphQl/etc/di.xml +++ b/app/code/Magento/GraphQl/etc/di.xml @@ -29,6 +29,7 @@ Magento\Framework\GraphQl\Config\Element\InterfaceFactory + Magento\Framework\GraphQl\Config\Element\UnionFactory Magento\Framework\GraphQl\Config\Element\TypeFactory Magento\Framework\GraphQl\Config\Element\InputFactory Magento\Framework\GraphQl\Config\Element\EnumFactory @@ -64,6 +65,7 @@ Magento\Framework\GraphQl\Schema\Type\Output\OutputTypeObject Magento\Framework\GraphQl\Schema\Type\Input\InputObjectType Magento\Framework\GraphQl\Schema\Type\Output\OutputInterfaceObject + Magento\Framework\GraphQl\Schema\Type\Output\OutputUnionObject Magento\Framework\GraphQl\Schema\Type\Enum\Enum @@ -78,6 +80,7 @@ Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\Fields Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\Interfaces + Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\Unions Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter\ResolveType @@ -85,6 +88,7 @@ + Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\UnionType Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\EnumType Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\ObjectType Magento\Framework\GraphQlSchemaStitching\GraphQlReader\Reader\InputObjectType diff --git a/app/code/Magento/GraphQl/etc/schema.graphqls b/app/code/Magento/GraphQl/etc/schema.graphqls index 2595ad09c072a..7366567c2b95d 100644 --- a/app/code/Magento/GraphQl/etc/schema.graphqls +++ b/app/code/Magento/GraphQl/etc/schema.graphqls @@ -30,14 +30,14 @@ directive @resolver(class: String="") on QUERY | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION - | INTERFACE - | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION -directive @typeResolver(class: String="") on INTERFACE | OBJECT +directive @typeResolver(class: String="") on UNION + | INTERFACE + | OBJECT directive @cache(cacheIdentity: String="" cacheable: Boolean=true) on QUERY diff --git a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/Item.php b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/Item.php index 1731a974aaed3..71ff93875f2c1 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/Item.php +++ b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/Item.php @@ -11,6 +11,9 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; +/** + * Resolver for Item + */ class Item implements ResolverInterface { /** diff --git a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/TestUnion.php b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/TestUnion.php new file mode 100644 index 0000000000000..592b0caaa88a3 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/TestUnion.php @@ -0,0 +1,34 @@ + 'custom_name1_value', + 'custom_name2' => 'custom_name2_value', + ]; + } +} diff --git a/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/UnionTypeResolver.php b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/UnionTypeResolver.php new file mode 100644 index 0000000000000..40cbdadb8a948 --- /dev/null +++ b/dev/tests/api-functional/_files/Magento/TestModuleGraphQlQuery/Model/Resolver/UnionTypeResolver.php @@ -0,0 +1,27 @@ +assertArrayHasKey('testItem', $response); } + + public function testQueryTestUnionResults() + { + $query = <<graphQlQuery($query); + + $this->assertArrayHasKey('testUnion', $response); + $testUnion = $response['testUnion']; + $this->assertArrayHasKey('custom_name1', $testUnion); + $this->assertEquals('custom_name1_value', $testUnion['custom_name1']); + $this->assertArrayNotHasKey('custom_name2', $testUnion); + } } diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/Type.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/Type.php index 20d017cc71062..073fb2e795e87 100644 --- a/lib/internal/Magento/Framework/GraphQl/Config/Element/Type.php +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/Type.php @@ -73,7 +73,15 @@ public function getFields() : array /** * Get interfaces the type implements, if any. Return an empty array if none are configured. * - * @return string[] + * Example return array( + * array( + * 'interface' => 'SomeDefinedTypeInterface', + * 'copyFields' => true + * ), + * ... + * ), + * + * @return array */ public function getInterfaces() : array { diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/UnionFactory.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/UnionFactory.php new file mode 100644 index 0000000000000..02d0a60064db6 --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/UnionFactory.php @@ -0,0 +1,69 @@ +objectManager = $objectManager; + } + + /** + * Instantiate an object representing 'union' GraphQL config element. + * + * @param array $data + * @return ConfigElementInterface + */ + public function createFromConfigData(array $data): ConfigElementInterface + { + return $this->create($data, $data['types'] ?? []); + } + + /** + * Create union object based off array of configured GraphQL. + * + * Union data must contain name, type resolver, and possible concrete types definitions + * The type resolver should point to an implementation of the TypeResolverInterface + * that decides what concrete GraphQL type to output. Description is the only optional field. + * + * @param array $unionData + * @param array $types + * @return UnionType + */ + public function create( + array $unionData, + array $types + ) : UnionType { + return $this->objectManager->create( + UnionType::class, + [ + 'name' => $unionData['name'], + 'typeResolver' => $unionData['typeResolver'], + 'types' => $types, + 'description' => isset($unionData['description']) ? $unionData['description'] : '' + ] + ); + } +} diff --git a/lib/internal/Magento/Framework/GraphQl/Config/Element/UnionInterface.php b/lib/internal/Magento/Framework/GraphQl/Config/Element/UnionInterface.php new file mode 100644 index 0000000000000..2d557e6dc5b84 --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQl/Config/Element/UnionInterface.php @@ -0,0 +1,23 @@ +name = $name; + $this->types = $types; + $this->typeResolver = $typeResolver; + $this->description = $description; + } + + /** + * Get the type name. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get a list of fields that make up the possible return or input values of a type. + * + * @return string[] + */ + public function getTypes(): array + { + return $this->types; + } + + /** + * Return the name of the resolver class that determines the concrete type to display in the result. + * + * @return string + */ + public function getTypeResolver(): string + { + return $this->typeResolver; + } + + /** + * Get a human-readable description of the type. + * + * @return string + */ + public function getDescription(): string + { + return $this->description; + } +} diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Filter.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Filter.php index 0e5feeba3bade..5ec80b1d4692c 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Filter.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Filter.php @@ -51,7 +51,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritDoc */ public function applyArgument( SearchCriteriaInterface $searchCriteria, diff --git a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Sort.php b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Sort.php index 6ecb1896d685a..d312837e41686 100644 --- a/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Sort.php +++ b/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Argument/SearchCriteria/ArgumentApplier/Sort.php @@ -33,7 +33,7 @@ public function __construct(SortOrderBuilder $sortOrderBuilder = null) } /** - * {@inheritdoc} + * @inheritDoc */ public function applyArgument( SearchCriteriaInterface $searchCriteria, diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Fields.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Fields.php index ad9fb675a6d70..3456f3c039a64 100644 --- a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Fields.php +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Fields.php @@ -10,6 +10,7 @@ use Magento\Framework\GraphQl\Config\Data\WrappedTypeProcessor; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Config\Element\TypeInterface; +use Magento\Framework\GraphQl\Config\ConfigElementInterface; use Magento\Framework\GraphQl\Schema\Type\Input\InputMapper; use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface; use Magento\Framework\GraphQl\Schema\Type\Output\OutputMapper; @@ -89,17 +90,20 @@ public function __construct( /** * @inheritdoc */ - public function format(TypeInterface $configElement, OutputTypeInterface $outputType): array + public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType): array { - $typeConfig = [ - 'fields' => function () use ($configElement, $outputType) { - $fieldsConfig = []; - foreach ($configElement->getFields() as $field) { - $fieldsConfig[$field->getName()] = $this->getFieldConfig($configElement, $outputType, $field); + $typeConfig = []; + if ($configElement instanceof TypeInterface) { + $typeConfig = [ + 'fields' => function () use ($configElement, $outputType) { + $fieldsConfig = []; + foreach ($configElement->getFields() as $field) { + $fieldsConfig[$field->getName()] = $this->getFieldConfig($configElement, $outputType, $field); + } + return $fieldsConfig; } - return $fieldsConfig; - } - ]; + ]; + } return $typeConfig; } diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Interfaces.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Interfaces.php index 659c3f604508d..761ba68e44521 100644 --- a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Interfaces.php +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Interfaces.php @@ -8,7 +8,7 @@ namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter; use Magento\Framework\GraphQl\Config\Element\Type; -use Magento\Framework\GraphQl\Config\Element\TypeInterface; +use Magento\Framework\GraphQl\Config\ConfigElementInterface; use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface; use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface; use Magento\Framework\GraphQl\Schema\Type\Output\OutputMapper; @@ -32,9 +32,9 @@ public function __construct(OutputMapper $outputMapper) } /** - * {@inheritDoc} + * @inheritDoc */ - public function format(TypeInterface $configElement, OutputTypeInterface $outputType) : array + public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array { $config = []; if ($configElement instanceof Type && !empty($configElement->getInterfaces())) { diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/ResolveType.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/ResolveType.php index 3a40e609eb952..553e8fe40efc2 100644 --- a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/ResolveType.php +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/ResolveType.php @@ -8,7 +8,8 @@ namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\Formatter; use Magento\Framework\GraphQl\Config\Element\InterfaceType; -use Magento\Framework\GraphQl\Config\Element\TypeInterface; +use Magento\Framework\GraphQl\Config\Element\UnionType; +use Magento\Framework\GraphQl\Config\ConfigElementInterface; use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface; use Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper\FormatterInterface; use Magento\Framework\ObjectManagerInterface; @@ -32,12 +33,12 @@ public function __construct(ObjectManagerInterface $objectManager) } /** - * {@inheritDoc} + * @inheritDoc */ - public function format(TypeInterface $configElement, OutputTypeInterface $outputType) : array + public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType) : array { $config = []; - if ($configElement instanceof InterfaceType) { + if ($configElement instanceof InterfaceType || $configElement instanceof UnionType) { $typeResolver = $this->objectManager->create($configElement->getTypeResolver()); $config['resolveType'] = function ($value) use ($typeResolver) { return $typeResolver->resolveType($value); diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Unions.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Unions.php new file mode 100644 index 0000000000000..75b6a58790a09 --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/Formatter/Unions.php @@ -0,0 +1,50 @@ +outputMapper = $outputMapper; + } + + /** + * @inheritDoc + */ + public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType): array + { + $config = []; + if ($configElement instanceof UnionType && !empty($configElement->getTypes())) { + $unionTypes = []; + foreach ($configElement->getTypes() as $unionName) { + $unionTypes[$unionName] = $this->outputMapper->getOutputType($unionName); + } + $config['types'] = $unionTypes; + } + + return $config; + } +} diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterComposite.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterComposite.php index 416b4122b7097..c36df11012017 100644 --- a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterComposite.php +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterComposite.php @@ -7,11 +7,11 @@ namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper; -use Magento\Framework\GraphQl\Config\Element\TypeInterface; +use Magento\Framework\GraphQl\Config\ConfigElementInterface; use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface; /** - * {@inheritdoc} + * @inheritDoc */ class FormatterComposite implements FormatterInterface { @@ -29,18 +29,19 @@ public function __construct(array $formatters) } /** - * {@inheritDoc} + * @inheritDoc */ - public function format(TypeInterface $configElement, OutputTypeInterface $outputType) : array + public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType): array { - $config = [ + $defaultConfig = [ 'name' => $configElement->getName(), 'description' => $configElement->getDescription() ]; + $formattedConfig = []; foreach ($this->formatters as $formatter) { - $config = array_merge($config, $formatter->format($configElement, $outputType)); + $formattedConfig[] = $formatter->format($configElement, $outputType); } - return $config; + return array_merge($defaultConfig, ...$formattedConfig); } } diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterInterface.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterInterface.php index 7d40b743a6a06..a99237aa8843a 100644 --- a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterInterface.php +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/ElementMapper/FormatterInterface.php @@ -7,7 +7,7 @@ namespace Magento\Framework\GraphQl\Schema\Type\Output\ElementMapper; -use Magento\Framework\GraphQl\Config\Element\TypeInterface as TypeElementInterface; +use Magento\Framework\GraphQl\Config\ConfigElementInterface; use Magento\Framework\GraphQl\Schema\Type\OutputTypeInterface; /** @@ -18,9 +18,9 @@ interface FormatterInterface /** * Convert GraphQL config element to the object compatible with GraphQL schema generator. * - * @param TypeElementInterface $configElement + * @param ConfigElementInterface $configElement * @param OutputTypeInterface $outputType * @return array */ - public function format(TypeElementInterface $configElement, OutputTypeInterface $outputType) : array; + public function format(ConfigElementInterface $configElement, OutputTypeInterface $outputType): array; } diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputMapper.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputMapper.php index 046eeb5b1f93d..afe0d84de26f8 100644 --- a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputMapper.php +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputMapper.php @@ -13,7 +13,7 @@ use Magento\Framework\Phrase; /** - * Map type names to their output type/interface/enum classes. + * Map type names to their output type/interface/union/enum classes. */ class OutputMapper { @@ -38,7 +38,7 @@ public function __construct( * @return OutputTypeInterface * @throws GraphQlInputException */ - public function getOutputType($typeName) + public function getOutputType(string $typeName) { $outputType = $this->typeRegistry->get($typeName); diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputUnionObject.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputUnionObject.php new file mode 100644 index 0000000000000..a63b7b7417527 --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/Output/OutputUnionObject.php @@ -0,0 +1,28 @@ +buildSchemaArray($configElement, $this)); + } +} diff --git a/lib/internal/Magento/Framework/GraphQl/Schema/Type/UnionType.php b/lib/internal/Magento/Framework/GraphQl/Schema/Type/UnionType.php new file mode 100644 index 0000000000000..a843c6c669acf --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQl/Schema/Type/UnionType.php @@ -0,0 +1,16 @@ + $type) { if (isset($type['implements']) && isset($type['implements'][$interface['name']]) @@ -253,7 +255,7 @@ private function convertInterfacesToAnnotations(string $graphQlSchemaContent): s private function addPlaceHolderInSchema(string $graphQlSchemaContent) :string { $placeholderField = self::GRAPHQL_PLACEHOLDER_FIELD_NAME; - $typesKindsPattern = '(type|interface|input)'; + $typesKindsPattern = '(type|interface|input|union)'; $enumKindsPattern = '(enum)'; $typeNamePattern = '([_A-Za-z][_0-9A-Za-z]+)'; $typeDefinitionPattern = '([^\{]*)(\{[\s\t\n\r^\}]*\})'; @@ -328,13 +330,14 @@ private static function getModuleNameForRelevantFile(string $file): string */ private function addModuleNameToTypes(array $source, string $filePath): array { - foreach ($source as $typeName => $type) { - if (!isset($type['module']) && ( - ($type['type'] === self::GRAPHQL_INTERFACE && isset($type['typeResolver'])) - || isset($type['implements']) - ) - ) { - $source[$typeName]['module'] = self::getModuleNameForRelevantFile($filePath); + foreach ($source as $typeName => $typeDefinition) { + if (!isset($typeDefinition['module'])) { + $hasTypeResolver = (bool)($typeDefinition['typeResolver'] ?? false); + $hasImplements = (bool)($typeDefinition['implements'] ?? false); + $typeDefinition = (bool)($typeDefinition['type'] ?? false); + if ((($typeDefinition === InterfaceType::GRAPHQL_INTERFACE && $hasTypeResolver) || $hasImplements)) { + $source[$typeName]['module'] = self::getModuleNameForRelevantFile($filePath); + } } } diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/EnumType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/EnumType.php index e4dec7afdab0a..c6e0481c7490e 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/EnumType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/EnumType.php @@ -15,6 +15,8 @@ */ class EnumType implements TypeMetaReaderInterface { + public const GRAPHQL_ENUM = 'graphql_enum'; + /** * @var DocReader */ @@ -30,14 +32,14 @@ public function __construct( } /** - * @inheritdoc + * @inheritDoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { if ($typeMeta instanceof \GraphQL\Type\Definition\EnumType) { $result = [ 'name' => $typeMeta->name, - 'type' => 'graphql_enum', + 'type' => self::GRAPHQL_ENUM, 'items' => [] // Populated later ]; foreach ($typeMeta->getValues() as $enumValueMeta) { diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php index 38159fac03b3b..2108a04d8a9ed 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InputObjectType.php @@ -17,6 +17,8 @@ */ class InputObjectType implements TypeMetaReaderInterface { + public const GRAPHQL_INPUT = 'graphql_input'; + /** * @var TypeMetaWrapperReader */ @@ -49,7 +51,7 @@ public function __construct( } /** - * @inheritdoc + * @inheritDoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { @@ -57,7 +59,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array $typeName = $typeMeta->name; $result = [ 'name' => $typeName, - 'type' => 'graphql_input', + 'type' => self::GRAPHQL_INPUT, 'fields' => [] // Populated later ]; $fields = $typeMeta->getFields(); diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php index baadb4be61cf2..76550469d409e 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/InterfaceType.php @@ -17,6 +17,8 @@ */ class InterfaceType implements TypeMetaReaderInterface { + public const GRAPHQL_INTERFACE = 'graphql_interface'; + /** * @var FieldMetaReader */ @@ -49,7 +51,7 @@ public function __construct( } /** - * @inheritdoc + * @inheritDoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { @@ -57,7 +59,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array $typeName = $typeMeta->name; $result = [ 'name' => $typeName, - 'type' => 'graphql_interface', + 'type' => self::GRAPHQL_INTERFACE, 'fields' => [] ]; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php index ba8e46dd60557..3ad6d69eb5c9c 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/ObjectType.php @@ -19,6 +19,8 @@ */ class ObjectType implements TypeMetaReaderInterface { + public const GRAPHQL_TYPE = 'graphql_type'; + /** * @var FieldMetaReader */ @@ -69,7 +71,7 @@ public function __construct( } /** - * @inheritdoc + * @inheritDoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array { @@ -77,7 +79,7 @@ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array $typeName = $typeMeta->name; $result = [ 'name' => $typeName, - 'type' => 'graphql_type', + 'type' => self::GRAPHQL_TYPE, 'fields' => [], // Populated later ]; diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/UnionType.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/UnionType.php new file mode 100644 index 0000000000000..5776901765b5a --- /dev/null +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/Reader/UnionType.php @@ -0,0 +1,106 @@ +fieldMetaReader = $fieldMetaReader; + $this->docReader = $docReader; + $this->cacheAnnotationReader = $cacheAnnotationReader ?? \Magento\Framework\App\ObjectManager::getInstance() + ->get(CacheAnnotationReader::class); + } + + /** + * @inheritDoc + */ + public function read(\GraphQL\Type\Definition\Type $typeMeta): array + { + if ($typeMeta instanceof \GraphQL\Type\Definition\UnionType) { + $typeName = $typeMeta->name; + $result = [ + 'name' => $typeName, + 'type' => self::GRAPHQL_UNION, + 'types' => [], + ]; + + $unionTypeResolver = $this->getUnionTypeResolver($typeMeta); + if (!empty($unionTypeResolver)) { + $result['typeResolver'] = $unionTypeResolver; + } + + foreach ($typeMeta->getTypes() as $type) { + $result['types'][] = $type->name; + } + + if ($this->docReader->read($typeMeta->astNode->directives)) { + $result['description'] = $this->docReader->read($typeMeta->astNode->directives); + } + + return $result; + } else { + return []; + } + } + + /** + * Retrieve the union type resolver if it exists from the meta data + * + * @param \GraphQL\Type\Definition\UnionType $unionTypeMeta + * @return string + */ + private function getUnionTypeResolver(\GraphQL\Type\Definition\UnionType $unionTypeMeta): string + { + /** @var \GraphQL\Language\AST\NodeList $directives */ + $directives = $unionTypeMeta->astNode->directives; + foreach ($directives as $directive) { + if ($directive->name->value == 'typeResolver') { + foreach ($directive->arguments as $directiveArgument) { + if ($directiveArgument->name->value == 'class') { + return $directiveArgument->value->value; + } + } + } + } + return ''; + } +} diff --git a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/TypeReaderComposite.php b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/TypeReaderComposite.php index e9b899bb2bb5b..614c1e3a743a0 100644 --- a/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/TypeReaderComposite.php +++ b/lib/internal/Magento/Framework/GraphQlSchemaStitching/GraphQlReader/TypeReaderComposite.php @@ -25,7 +25,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritDoc */ public function read(\GraphQL\Type\Definition\Type $typeMeta) : array {