diff --git a/CHANGELOG.md b/CHANGELOG.md index 52050f5f0..7283ddb31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ You can find and compare releases at the [GitHub release page](https://github.co ## Unreleased +### Changed + +- Allow omitting deprecated introspection arguments/fields for legacy servers https://github.com/webonyx/graphql-php/pull/1849 + ## v15.34.0 ### Added diff --git a/src/Type/Introspection.php b/src/Type/Introspection.php index 648540ea6..1864efced 100644 --- a/src/Type/Introspection.php +++ b/src/Type/Introspection.php @@ -30,6 +30,7 @@ * @phpstan-type IntrospectionOptions array{ * descriptions?: bool, * directiveIsRepeatable?: bool, + * includeDeprecated?: bool, * schemaDescription?: bool, * specifiedByURL?: bool, * typeIsOneOf?: bool, @@ -42,6 +43,12 @@ * - directiveIsRepeatable * Include field `isRepeatable` for directives? * Default: false + * - includeDeprecated + * Include deprecated fields/args/enum values/input fields and related indicators + * (isDeprecated/deprecationReason) in the introspection query + * Default: true + * + * @see https://graphql-ruby.org/api-doc/1.12.1/GraphQL/Introspection.html * - schemaDescription * Include `description` on the schema? * Default: false @@ -51,7 +58,6 @@ * - typeIsOneOf * Include field `isOneOf` for types? * Default: false - * * @see \GraphQL\Tests\Type\IntrospectionTest */ class Introspection @@ -93,6 +99,7 @@ public static function getIntrospectionQuery(array $options = []): string $optionsWithDefaults = array_merge([ 'descriptions' => true, 'directiveIsRepeatable' => false, + 'includeDeprecated' => true, 'schemaDescription' => false, 'specifiedByURL' => false, 'typeIsOneOf' => false, @@ -113,6 +120,13 @@ public static function getIntrospectionQuery(array $options = []): string $typeIsOneOf = $optionsWithDefaults['typeIsOneOf'] ? 'isOneOf' : ''; + $includeDeprecated = $optionsWithDefaults['includeDeprecated']; + $includeDeprecatedArg = $includeDeprecated + ? '(includeDeprecated: true)' + : ''; + $deprecationIndicators = $includeDeprecated + ? " isDeprecated\n deprecationReason" + : ''; return << $value['description'], - 'deprecationReason' => $value['deprecationReason'], + 'deprecationReason' => $value['deprecationReason'] ?? null, ]; } @@ -480,7 +480,7 @@ private function buildFieldDefMap(array $typeIntrospection): array $map[$field['name']] = [ 'description' => $field['description'], - 'deprecationReason' => $field['deprecationReason'], + 'deprecationReason' => $field['deprecationReason'] ?? null, 'type' => $this->getOutputType($field['type']), 'args' => $this->buildInputValueDefMap($field['args']), ]; diff --git a/tests/Type/IntrospectionTest.php b/tests/Type/IntrospectionTest.php index 08bc8489d..31cac0878 100644 --- a/tests/Type/IntrospectionTest.php +++ b/tests/Type/IntrospectionTest.php @@ -2096,6 +2096,28 @@ public function testIncludeDescriptionFieldOnSchema(): void self::assertCount(0, $matches[0]); } + public function testExcludeDeprecatedFieldsAndIndicatorsWhenDisabled(): void + { + $source = Introspection::getIntrospectionQuery(['includeDeprecated' => false]); + + self::assertStringNotContainsString('includeDeprecated: true', $source); + self::assertStringNotContainsString('includeDeprecated: false', $source); + self::assertStringContainsString('args {', $source); + self::assertStringContainsString('fields {', $source); + self::assertStringContainsString('inputFields {', $source); + self::assertStringContainsString('enumValues {', $source); + self::assertStringNotContainsString('isDeprecated', $source); + self::assertStringNotContainsString('deprecationReason', $source); + } + + /** @see it('keeps deprecated args enabled by default') */ + public function testIncludeDeprecatedArgumentsByDefault(): void + { + $source = Introspection::getIntrospectionQuery(); + + self::assertStringContainsString('(includeDeprecated: true)', $source); + } + /** @see it('include "specifiedBy" field') */ public function testSpecifiedByURLNotIncludedInIntrospectionQueryByDefault(): void { diff --git a/tests/Utils/BuildClientSchemaTest.php b/tests/Utils/BuildClientSchemaTest.php index 8d7e17599..883f7c8f3 100644 --- a/tests/Utils/BuildClientSchemaTest.php +++ b/tests/Utils/BuildClientSchemaTest.php @@ -166,6 +166,38 @@ public function testUsesBuiltInScalarsWhenPossible(): void ); } + public function testBuildsSchemaFromIntrospectionWithoutDeprecatedFields(): void + { + $sdl = ' + type Query { + active: String + legacy: String @deprecated(reason: "Use active") + } + + enum Status { + OK + OLD @deprecated(reason: "Use OK") + } + '; + + $schema = BuildSchema::build($sdl); + $introspection = Introspection::fromSchema($schema, [ + 'includeDeprecated' => false, + ]); + + $clientSchema = BuildClientSchema::build($introspection); + + $queryType = $clientSchema->getQueryType(); + self::assertNotNull($queryType); + self::assertArrayHasKey('active', $queryType->getFields()); + self::assertArrayNotHasKey('legacy', $queryType->getFields()); + + $statusEnum = $clientSchema->getType('Status'); + self::assertInstanceOf(EnumType::class, $statusEnum); + self::assertNotNull($statusEnum->getValue('OK')); + self::assertNull($statusEnum->getValue('OLD')); + } + /** it('includes standard types only if they are used', () => {. */ public function testIncludesStandardTypesOnlyIfTheyAreUsed(): void {