diff --git a/src/GraphQL/DirectiveProviderExtensionInterface.php b/src/GraphQL/DirectiveProviderExtensionInterface.php new file mode 100644 index 000000000..759111408 --- /dev/null +++ b/src/GraphQL/DirectiveProviderExtensionInterface.php @@ -0,0 +1,20 @@ +extensionManager->createInstance($id); }, array_filter($this->getConfiguration()['extensions'])); + + $schemaDocument = $this->getSchemaDocument($extensions); + // Iterate through all extensions and pass them the current schema, so they + // can act on it. + foreach ($extensions as $extension) { + if ($extension instanceof ParentAwareSchemaExtensionInterface) { + $extension->setParentSchemaDocument($schemaDocument); + } + } + + return $extensions; } /** * {@inheritdoc} */ protected function getSchemaDefinition() { - return <<getDirectiveDefinitions(); } + } - type Query + // Attempt to load a schema file and return it instead of the hardcoded + // empty schema. + $id = $this->getPluginId(); + $definition = $this->getPluginDefinition(); + $module = $this->moduleHandler->getModule($definition['provider']); + $path = 'graphql/' . $id . '.graphqls'; + $file = $module->getPath() . '/' . $path; + + if (!file_exists($file)) { + $schema[] = <<parentAst = $document; + } + + /** + * {@inheritDoc} + */ + public function getDirectiveDefinitions(): string { + return <<getTypesWithDimensions(); + + foreach ($typesWithDimensions as $typeWithDimensions) { + $schema[] = "extend type $typeWithDimensions[type_name] {"; + $schema[] = " width: String!"; + $schema[] = " height: String!"; + if (isset($typeWithDimensions['args']['includeDepth']) && $typeWithDimensions['args']['includeDepth']) { + $schema[] = " depth: String!"; + } + $schema[] = "}"; + } + + array_unshift($schema, parent::getExtensionDefinition()); + return implode("\n", $schema); + } + + /** + * {@inheritDoc} + */ + public function registerResolvers(ResolverRegistryInterface $registry): void { + $builder = new ResolverBuilder(); + $registry->addFieldResolver('Query', 'cars', $builder->callback(function () { + return [(object) ['brand' => 'Brand', 'model' => 'Model']]; + })); + foreach ($this->getTypesWithDimensions() as $typeWithDimensions) { + $registry->addFieldResolver($typeWithDimensions['type_name'], 'width', $builder->callback(function () { + return '1'; + })); + $registry->addFieldResolver($typeWithDimensions['type_name'], 'height', $builder->callback(function () { + return '1'; + })); + if (isset($typeWithDimensions['args']['includeDepth']) && $typeWithDimensions['args']['includeDepth']) { + $registry->addFieldResolver($typeWithDimensions['type_name'], 'depth', $builder->callback(function () { + return '1'; + })); + } + } + } + + /** + * Retrieve all directive calls in the host schema. + * + * @throws \Drupal\Component\Plugin\Exception\PluginException + */ + public function getTypesWithDimensions(): array { + if (count($this->typesWithDimensions) === 0) { + // Search for object type definitions ... + foreach ($this->parentAst->definitions->getIterator() as $definition) { + // ... that have directives. + if ($definition instanceof ObjectTypeDefinitionNode) { + foreach ($definition->directives->getIterator() as $directive) { + /** @var \GraphQL\Language\AST\DirectiveNode $directive */ + $directiveName = $directive->name->value; + if ($directiveName != 'dimensions') { + continue; + } + $typeName = $definition->name->value; + $args = []; + foreach ($directive->arguments->getIterator() as $arg) { + /** @var \GraphQL\Language\AST\ArgumentNode $arg */ + $args[$arg->name->value] = $arg->value->value; + } + $this->typesWithDimensions[] = [ + 'directive_name' => $directiveName, + 'type_name' => $typeName, + 'args' => $args, + ]; + } + } + } + } + return $this->typesWithDimensions; + } + +} diff --git a/tests/src/Kernel/ExtensionDirectivesTest.php b/tests/src/Kernel/ExtensionDirectivesTest.php new file mode 100644 index 000000000..672047786 --- /dev/null +++ b/tests/src/Kernel/ExtensionDirectivesTest.php @@ -0,0 +1,77 @@ +createTestServer( + 'composable', + '/extension-directives-test', + [ + 'schema_configuration' => [ + 'composable' => [ + 'extensions' => [ + 'extension_directives_test' => 'extension_directives_test', + ], + ], + ], + ] + ); + } + + /** + * Tests that retrieving an entity definition works. + */ + public function testFields(): void { + $query = <<assertResults($query, [], + [ + 'cars' => + [ + [ + 'brand' => 'Brand', + 'model' => 'Model', + 'width' => '1', + 'height' => '1', + 'depth' => '1', + ], + ], + ] + ); + } + +}