From df4d52ccaca6cd308a5d26543a4eef2838993602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Owczarczyk?= Date: Wed, 30 Jun 2021 13:48:49 +0200 Subject: [PATCH 1/6] feat: added directives to extensions --- .../DirectiveProviderExtensionInterface.php | 19 +++ .../ParentAwareSchemaExtensionInterface.php | 23 +++ .../GraphQL/Schema/ComposableSchema.php | 46 +++++- .../extension_directives_test.base.graphqls | 4 + ...tension_directives_test.extension.graphqls | 3 + ...graphql_extension_directives_test.info.yml | 7 + ...ExtensionDirectivesTestSchemaExtension.php | 133 ++++++++++++++++++ tests/src/Kernel/ExtensionDirectivesTest.php | 79 +++++++++++ 8 files changed, 309 insertions(+), 5 deletions(-) create mode 100644 src/GraphQL/DirectiveProviderExtensionInterface.php create mode 100644 src/GraphQL/ParentAwareSchemaExtensionInterface.php create mode 100644 tests/modules/graphql_extension_directives_test/graphql/extension_directives_test.base.graphqls create mode 100644 tests/modules/graphql_extension_directives_test/graphql/extension_directives_test.extension.graphqls create mode 100644 tests/modules/graphql_extension_directives_test/graphql_extension_directives_test.info.yml create mode 100644 tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php create mode 100644 tests/src/Kernel/ExtensionDirectivesTest.php diff --git a/src/GraphQL/DirectiveProviderExtensionInterface.php b/src/GraphQL/DirectiveProviderExtensionInterface.php new file mode 100644 index 000000000..2baabdbee --- /dev/null +++ b/src/GraphQL/DirectiveProviderExtensionInterface.php @@ -0,0 +1,19 @@ +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) { + $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 && $definition->directives) { + 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..ab2aa0b97 --- /dev/null +++ b/tests/src/Kernel/ExtensionDirectivesTest.php @@ -0,0 +1,79 @@ +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', + ] + ]]); + } + +} From 4760e4489ee4b3bffa9f8156e2a4e68cbd3e7f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Owczarczyk?= Date: Wed, 30 Jun 2021 14:00:26 +0200 Subject: [PATCH 2/6] chore: make phpstan happy --- .../ExtensionDirectivesTestSchemaExtension.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php b/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php index 7e884d771..0c23dae69 100644 --- a/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php +++ b/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php @@ -56,6 +56,7 @@ public function getDirectiveDefinitions(): string { * {@inheritDoc} */ public function getExtensionDefinition() { + $schema = []; $typesWithDimensions = $this->getTypesWithDimensions(); foreach ($typesWithDimensions as $typeWithDimensions) { @@ -75,7 +76,7 @@ public function getExtensionDefinition() { /** * {@inheritDoc} */ - public function registerResolvers(ResolverRegistryInterface $registry) { + public function registerResolvers(ResolverRegistryInterface $registry): void { $builder = new ResolverBuilder(); $registry->addFieldResolver('Query', 'cars', $builder->callback(function () { return [(object)['brand' => 'Brand', 'model' => 'Model']]; @@ -105,7 +106,7 @@ public function getTypesWithDimensions(): array { // Search for object type definitions ... foreach ($this->parentAst->definitions->getIterator() as $definition) { // ... that have directives. - if ($definition instanceof ObjectTypeDefinitionNode && $definition->directives) { + if ($definition instanceof ObjectTypeDefinitionNode) { foreach ($definition->directives->getIterator() as $directive) { /** @var \GraphQL\Language\AST\DirectiveNode $directive */ $directiveName = $directive->name->value; From 5204494e5912fe22019644624256e143e790d98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Owczarczyk?= Date: Wed, 30 Jun 2021 14:16:54 +0200 Subject: [PATCH 3/6] chore: make phpstan happier --- .../DirectiveProviderExtensionInterface.php | 1 + .../ParentAwareSchemaExtensionInterface.php | 3 +- .../GraphQL/Schema/ComposableSchema.php | 5 +-- ...ExtensionDirectivesTestSchemaExtension.php | 9 ++--- tests/src/Kernel/ExtensionDirectivesTest.php | 35 ++++++++----------- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/GraphQL/DirectiveProviderExtensionInterface.php b/src/GraphQL/DirectiveProviderExtensionInterface.php index 2baabdbee..759111408 100644 --- a/src/GraphQL/DirectiveProviderExtensionInterface.php +++ b/src/GraphQL/DirectiveProviderExtensionInterface.php @@ -13,6 +13,7 @@ interface DirectiveProviderExtensionInterface { * Retrieve all directive definitions as a string. * * @return string + * Directive definitions in SDL. */ public function getDirectiveDefinitions() : string; diff --git a/src/GraphQL/ParentAwareSchemaExtensionInterface.php b/src/GraphQL/ParentAwareSchemaExtensionInterface.php index 9d0a93175..2b18c71ba 100644 --- a/src/GraphQL/ParentAwareSchemaExtensionInterface.php +++ b/src/GraphQL/ParentAwareSchemaExtensionInterface.php @@ -15,8 +15,7 @@ interface ParentAwareSchemaExtensionInterface { * Pass the parent schema document to the extension. * * @param \GraphQL\Language\AST\DocumentNode $document - * - * @return void + * The parent schema document. */ public function setParentSchemaDocument(DocumentNode $document); diff --git a/src/Plugin/GraphQL/Schema/ComposableSchema.php b/src/Plugin/GraphQL/Schema/ComposableSchema.php index 084360618..3ff2062a5 100644 --- a/src/Plugin/GraphQL/Schema/ComposableSchema.php +++ b/src/Plugin/GraphQL/Schema/ComposableSchema.php @@ -38,7 +38,7 @@ protected function getExtensions() { $schemaDocument = $this->getSchemaDocument($extensions); // Iterate through all extensions and pass them the current schema, so they // can act on it. - foreach($extensions as $extension) { + foreach ($extensions as $extension) { if ($extension instanceof ParentAwareSchemaExtensionInterface) { $extension->setParentSchemaDocument($schemaDocument); } @@ -77,7 +77,8 @@ protected function getSchemaDefinition() { type Query GQL; - } else { + } + else { $schema[] = file_get_contents($file); } diff --git a/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php b/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php index 0c23dae69..59047ee2e 100644 --- a/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php +++ b/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php @@ -19,8 +19,7 @@ * schema = "composable" * ) */ -class ExtensionDirectivesTestSchemaExtension extends SdlSchemaExtensionPluginBase - implements ParentAwareSchemaExtensionInterface, DirectiveProviderExtensionInterface { +class ExtensionDirectivesTestSchemaExtension extends SdlSchemaExtensionPluginBase implements ParentAwareSchemaExtensionInterface, DirectiveProviderExtensionInterface { /** * The parent schema's AST. @@ -30,6 +29,8 @@ class ExtensionDirectivesTestSchemaExtension extends SdlSchemaExtensionPluginBas protected $parentAst; /** + * Stores found types with the dimensions directive. + * * @var array */ protected $typesWithDimensions = []; @@ -79,9 +80,9 @@ public function getExtensionDefinition() { public function registerResolvers(ResolverRegistryInterface $registry): void { $builder = new ResolverBuilder(); $registry->addFieldResolver('Query', 'cars', $builder->callback(function () { - return [(object)['brand' => 'Brand', 'model' => 'Model']]; + return [(object) ['brand' => 'Brand', 'model' => 'Model']]; })); - foreach($this->getTypesWithDimensions() as $typeWithDimensions) { + foreach ($this->getTypesWithDimensions() as $typeWithDimensions) { $registry->addFieldResolver($typeWithDimensions['type_name'], 'width', $builder->callback(function () { return '1'; })); diff --git a/tests/src/Kernel/ExtensionDirectivesTest.php b/tests/src/Kernel/ExtensionDirectivesTest.php index ab2aa0b97..045aeb60d 100644 --- a/tests/src/Kernel/ExtensionDirectivesTest.php +++ b/tests/src/Kernel/ExtensionDirectivesTest.php @@ -2,13 +2,6 @@ namespace Drupal\Tests\graphql\Kernel; -use Drupal\Core\Entity\Entity\EntityFormDisplay; -use Drupal\Core\Field\FieldStorageDefinitionInterface; -use Drupal\field\Entity\FieldConfig; -use Drupal\field\Entity\FieldStorageConfig; -use Drupal\graphql\GraphQL\ResolverBuilder; -use Drupal\node\Entity\NodeType; - /** * Test the entity_definition data producer and friends. * @@ -17,7 +10,7 @@ class ExtensionDirectivesTest extends GraphQLTestBase { /** - * {@inheritdoc } + * {@inheritdoc} */ protected $strictConfigSchema = FALSE; @@ -42,10 +35,10 @@ public function setUp(): void { 'composable' => [ 'extensions' => [ 'extension_directives_test' => 'extension_directives_test' - ] - ] - ] - ] + ], + ], + ], + ], ); } @@ -65,15 +58,17 @@ public function testFields(): void { } GQL; - $this->assertResults($query, [], ['cars' => [ + $this->assertResults($query, [], ['cars' => [ - 'brand' => 'Brand', - 'model' => 'Model', - 'width' => '1', - 'height' => '1', - 'depth' => '1', - ] - ]]); + [ + 'brand' => 'Brand', + 'model' => 'Model', + 'width' => '1', + 'height' => '1', + 'depth' => '1', + ], + ], + ]); } } From bb0dcb9c6c4ba9070e71588110587a777e7d3748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Owczarczyk?= Date: Wed, 30 Jun 2021 14:22:34 +0200 Subject: [PATCH 4/6] chore: make phpstan even happier --- src/GraphQL/ParentAwareSchemaExtensionInterface.php | 2 +- .../SchemaExtension/ExtensionDirectivesTestSchemaExtension.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GraphQL/ParentAwareSchemaExtensionInterface.php b/src/GraphQL/ParentAwareSchemaExtensionInterface.php index 2b18c71ba..ff973ebde 100644 --- a/src/GraphQL/ParentAwareSchemaExtensionInterface.php +++ b/src/GraphQL/ParentAwareSchemaExtensionInterface.php @@ -17,6 +17,6 @@ interface ParentAwareSchemaExtensionInterface { * @param \GraphQL\Language\AST\DocumentNode $document * The parent schema document. */ - public function setParentSchemaDocument(DocumentNode $document); + public function setParentSchemaDocument(DocumentNode $document): void; } diff --git a/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php b/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php index 59047ee2e..9166bf70d 100644 --- a/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php +++ b/tests/modules/graphql_extension_directives_test/src/Plugin/GraphQL/SchemaExtension/ExtensionDirectivesTestSchemaExtension.php @@ -38,7 +38,7 @@ class ExtensionDirectivesTestSchemaExtension extends SdlSchemaExtensionPluginBas /** * {@inheritDoc} */ - public function setParentSchemaDocument($document) { + public function setParentSchemaDocument($document): void { $this->parentAst = $document; } From 96aa7b35a4aec99dde941f473c1b23fce0e96c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Owczarczyk?= Date: Wed, 30 Jun 2021 14:27:52 +0200 Subject: [PATCH 5/6] chore: smiling happy people holding hands --- tests/src/Kernel/ExtensionDirectivesTest.php | 25 +++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/src/Kernel/ExtensionDirectivesTest.php b/tests/src/Kernel/ExtensionDirectivesTest.php index 045aeb60d..5e6816193 100644 --- a/tests/src/Kernel/ExtensionDirectivesTest.php +++ b/tests/src/Kernel/ExtensionDirectivesTest.php @@ -34,7 +34,7 @@ public function setUp(): void { 'schema_configuration' => [ 'composable' => [ 'extensions' => [ - 'extension_directives_test' => 'extension_directives_test' + 'extension_directives_test' => 'extension_directives_test', ], ], ], @@ -58,17 +58,20 @@ public function testFields(): void { } GQL; - $this->assertResults($query, [], ['cars' => + $this->assertResults($query, [], [ - [ - 'brand' => 'Brand', - 'model' => 'Model', - 'width' => '1', - 'height' => '1', - 'depth' => '1', - ], - ], - ]); + 'cars' => + [ + [ + 'brand' => 'Brand', + 'model' => 'Model', + 'width' => '1', + 'height' => '1', + 'depth' => '1', + ], + ], + ] + ); } } From 6b4c1054755ac90ca3269e3318eb3c2c3f094d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Owczarczyk?= Date: Wed, 30 Jun 2021 14:33:07 +0200 Subject: [PATCH 6/6] chore: fixed a syntax error in php 7.2 --- tests/src/Kernel/ExtensionDirectivesTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/Kernel/ExtensionDirectivesTest.php b/tests/src/Kernel/ExtensionDirectivesTest.php index 5e6816193..672047786 100644 --- a/tests/src/Kernel/ExtensionDirectivesTest.php +++ b/tests/src/Kernel/ExtensionDirectivesTest.php @@ -38,7 +38,7 @@ public function setUp(): void { ], ], ], - ], + ] ); }