From d524cb9f08f7a6be1bc07b913da151719f9d04b6 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 8 Jul 2025 11:56:39 -0600 Subject: [PATCH 1/6] no message --- src/Utils/ASTDefinitionBuilder.php | 26 +++++++++++++++++++++++++- src/Utils/SchemaPrinter.php | 1 + tests/Utils/SchemaPrinterTest.php | 22 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/Utils/ASTDefinitionBuilder.php b/src/Utils/ASTDefinitionBuilder.php index c11fc6b55..5f39d001a 100644 --- a/src/Utils/ASTDefinitionBuilder.php +++ b/src/Utils/ASTDefinitionBuilder.php @@ -536,16 +536,40 @@ private function makeScalarDef(ScalarTypeDefinitionNode $def): CustomScalarType ]); } - /** @throws InvariantViolation */ + /** + * @throws \Exception + * @throws \ReflectionException + * @throws InvariantViolation + */ private function makeInputObjectDef(InputObjectTypeDefinitionNode $def): InputObjectType { $name = $def->name->value; /** @var array $extensionASTNodes (proven by schema validation) */ $extensionASTNodes = $this->typeExtensionsMap[$name] ?? []; + // Check for @oneOf directive in the definition node + $isOneOf = Values::getDirectiveValues( + Directive::oneOfDirective(), + $def + ) !== null; + + // Check for @oneOf directive in extension nodes + if (! $isOneOf) { + foreach ($extensionASTNodes as $extensionNode) { + if (Values::getDirectiveValues( + Directive::oneOfDirective(), + $extensionNode + ) !== null) { + $isOneOf = true; + break; + } + } + } + return new InputObjectType([ 'name' => $name, 'description' => $def->description->value ?? null, + 'isOneOf' => $isOneOf, 'fields' => fn (): array => $this->makeInputFields([$def, ...$extensionASTNodes]), 'astNode' => $def, 'extensionASTNodes' => $extensionASTNodes, diff --git a/src/Utils/SchemaPrinter.php b/src/Utils/SchemaPrinter.php index 5c9d8a525..d54244b7d 100644 --- a/src/Utils/SchemaPrinter.php +++ b/src/Utils/SchemaPrinter.php @@ -563,6 +563,7 @@ protected static function printInputObject(InputObjectType $type, array $options return static::printDescription($options, $type) . "input {$type->name}" + . ($type->isOneOf() ? ' @oneOf' : '') . static::printBlock($fields); } diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index c3f4bda0d..e58e38055 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -752,6 +752,28 @@ public function testInputType(): void ); } + /** @see it('Print Input Type with @oneOf directive') */ + public function testInputTypeWithOneOfDirective(): void + { + $inputType = new InputObjectType([ + 'name' => 'InputType', + 'isOneOf' => true, + 'fields' => ['int' => ['type' => Type::int()]], + ]); + + $schema = new Schema(['types' => [$inputType]]); + + self::assertPrintedSchemaEquals( + <<<'GRAPHQL' + input InputType @oneOf { + int: Int + } + + GRAPHQL, + $schema + ); + } + /** @see it('Custom Scalar') */ public function testCustomScalar(): void { From 84272b8fffac7cdd3323aa540788aabf837c286f Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Tue, 8 Jul 2025 12:03:40 -0600 Subject: [PATCH 2/6] - add test for extension nodes --- tests/Utils/BuildSchemaTest.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/Utils/BuildSchemaTest.php b/tests/Utils/BuildSchemaTest.php index 11cd8c2d8..1b87ea784 100644 --- a/tests/Utils/BuildSchemaTest.php +++ b/tests/Utils/BuildSchemaTest.php @@ -1042,6 +1042,39 @@ public function testCorrectlyExtendInputObjectType(): void self::assertSame($inputSDL, $this->printAllASTNodes($someInput)); } + /** @see it('Correctly extend input object type with @oneOf directive') */ + public function testCorrectlyExtendInputObjectTypeWithOneOfDirective(): void + { + $inputSDL = <<<'GRAPHQL' + input SomeInput { + first: String + } + + extend input SomeInput @oneOf { + second: Int + } + + GRAPHQL; + + $schema = BuildSchema::build($inputSDL); + + $someInput = $schema->getType('SomeInput'); + assert($someInput instanceof InputObjectType); + + // Verify that the @oneOf directive from the extension is properly applied + self::assertTrue($someInput->isOneOf()); + + $expectedSomeInputSDL = <<<'GRAPHQL' + input SomeInput @oneOf { + first: String + second: Int + } + GRAPHQL; + + self::assertSame($expectedSomeInputSDL, SchemaPrinter::printType($someInput)); + self::assertSame($inputSDL, $this->printAllASTNodes($someInput)); + } + /** @see it('Correctly assign AST nodes') */ public function testCorrectlyAssignASTNodes(): void { From dd9a9302fef3e91a11b138b5090716d4422a4213 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Wed, 9 Jul 2025 11:01:00 -0600 Subject: [PATCH 3/6] Update tests/Utils/SchemaPrinterTest.php Co-authored-by: Benedikt Franke --- tests/Utils/SchemaPrinterTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index e58e38055..68926b5e1 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -758,7 +758,9 @@ public function testInputTypeWithOneOfDirective(): void $inputType = new InputObjectType([ 'name' => 'InputType', 'isOneOf' => true, - 'fields' => ['int' => ['type' => Type::int()]], + 'fields' => [ + 'int' => Type::int(), + ], ]); $schema = new Schema(['types' => [$inputType]]); From cdc8bfa77b6b8c92e945f32d442478d7c3271ae3 Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Wed, 9 Jul 2025 11:07:40 -0600 Subject: [PATCH 4/6] - use variable for oneOfDirective --- src/Utils/ASTDefinitionBuilder.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Utils/ASTDefinitionBuilder.php b/src/Utils/ASTDefinitionBuilder.php index 5f39d001a..66c51b24f 100644 --- a/src/Utils/ASTDefinitionBuilder.php +++ b/src/Utils/ASTDefinitionBuilder.php @@ -547,9 +547,11 @@ private function makeInputObjectDef(InputObjectTypeDefinitionNode $def): InputOb /** @var array $extensionASTNodes (proven by schema validation) */ $extensionASTNodes = $this->typeExtensionsMap[$name] ?? []; + $oneOfDirective = Directive::oneOfDirective(); + // Check for @oneOf directive in the definition node $isOneOf = Values::getDirectiveValues( - Directive::oneOfDirective(), + $oneOfDirective, $def ) !== null; @@ -557,7 +559,7 @@ private function makeInputObjectDef(InputObjectTypeDefinitionNode $def): InputOb if (! $isOneOf) { foreach ($extensionASTNodes as $extensionNode) { if (Values::getDirectiveValues( - Directive::oneOfDirective(), + $oneOfDirective, $extensionNode ) !== null) { $isOneOf = true; From c0b075017884c0dbf162b7068b252c2d2d3f04fe Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Wed, 9 Jul 2025 11:12:09 -0600 Subject: [PATCH 5/6] - phpcs --- tests/Utils/SchemaPrinterTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Utils/SchemaPrinterTest.php b/tests/Utils/SchemaPrinterTest.php index 514f43f89..b72500aa4 100644 --- a/tests/Utils/SchemaPrinterTest.php +++ b/tests/Utils/SchemaPrinterTest.php @@ -775,7 +775,9 @@ public function testInputTypeWithOneOfDirective(): void ], ]); - $schema = new Schema(['types' => [$inputType]]); + $schema = new Schema([ + 'types' => [$inputType], + ]); self::assertPrintedSchemaEquals( <<<'GRAPHQL' From 9b203ab9318b789d86de8be651fb38fc74402dea Mon Sep 17 00:00:00 2001 From: Jason Bahl Date: Wed, 9 Jul 2025 11:21:57 -0600 Subject: [PATCH 6/6] Update src/Utils/ASTDefinitionBuilder.php Co-authored-by: Benedikt Franke --- src/Utils/ASTDefinitionBuilder.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Utils/ASTDefinitionBuilder.php b/src/Utils/ASTDefinitionBuilder.php index 66c51b24f..07764bb9d 100644 --- a/src/Utils/ASTDefinitionBuilder.php +++ b/src/Utils/ASTDefinitionBuilder.php @@ -550,18 +550,12 @@ private function makeInputObjectDef(InputObjectTypeDefinitionNode $def): InputOb $oneOfDirective = Directive::oneOfDirective(); // Check for @oneOf directive in the definition node - $isOneOf = Values::getDirectiveValues( - $oneOfDirective, - $def - ) !== null; + $isOneOf = Values::getDirectiveValues($oneOfDirective, $def) !== null; // Check for @oneOf directive in extension nodes if (! $isOneOf) { foreach ($extensionASTNodes as $extensionNode) { - if (Values::getDirectiveValues( - $oneOfDirective, - $extensionNode - ) !== null) { + if (Values::getDirectiveValues($oneOfDirective, $extensionNode) !== null) { $isOneOf = true; break; }