Skip to content

Commit

Permalink
Merge f0660db into 3d8a771
Browse files Browse the repository at this point in the history
  • Loading branch information
realFlowControl committed Feb 26, 2020
2 parents 3d8a771 + f0660db commit 72ed388
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 2 deletions.
50 changes: 50 additions & 0 deletions docs/type_mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,56 @@ If you want to add support for your own library, this is not extremely difficult
"RootTypeMapper" with GraphQLite. You can learn more about <em>type mappers</em> in the <a href="internals.md">"internals" documentation</a>
and <a href="https://github.com/thecodingmachine/graphqlite/blob/master/src/Mappers/Root/MyCLabsEnumTypeMapper.php">copy/paste and adapt the root type mapper used for myclabs/php-enum</a>.</div>

## Deprecation of fields

You can mark a field as deprecated in your GraphQL Schema by just annotating it with the `@deprecated` PHPDoc annotation.

```php
namespace App\Entities;

use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Type;

/**
* @Type()
*/
class Product
{
// ...

/**
* @Field()
*/
public function getName(): string
{
return $this->name;
}

/**
* @Field()
* @deprecated use field `name` instead
*/
public function getProductName(): string
{
return $this->name;
}
}
```

This will add the `@deprecated` directive to the field in the GraphQL Schema which sets the `isDeprecated` field to `true` and adds the reason to the `deprecationReason` field in an introspection query. Fields marked as deprecated can still be queried, but will be returned in an introspection query only if `includeDeprecated` is set to `true`.

```graphql
query {
__type(name: "Product") {
fields(includeDeprecated: true) {
name
isDeprecated
deprecationReason
 }
 }
}
```

## More scalar types

<small>Available in GraphQLite 4.0+</small>
Expand Down
12 changes: 12 additions & 0 deletions src/FieldsBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
use function array_merge;
use function array_shift;
use function assert;
use function count;
use function get_class;
use function get_parent_class;
use function is_string;
use function reset;
use function trim;
use function ucfirst;

/**
Expand Down Expand Up @@ -241,6 +243,11 @@ private function getFieldsByAnnotations($controller, string $annotationName, boo
$docBlockObj = $this->cachedDocBlockFactory->getDocBlock($refMethod);
$docBlockComment = $docBlockObj->getSummary() . "\n" . $docBlockObj->getDescription()->render();

$deprecated = $docBlockObj->getTagsByName('deprecated');
if (count($deprecated) >= 1) {
$fieldDescriptor->setDeprecationReason(trim((string) $deprecated[0]));
}

$methodName = $refMethod->getName();
$name = $queryAnnotation->getName() ?: $this->namingStrategy->getFieldNameFromMethodName($methodName);

Expand Down Expand Up @@ -403,6 +410,11 @@ private function getQueryFieldsFromSourceFields(array $sourceFields, ReflectionC
$docBlockObj = $this->cachedDocBlockFactory->getDocBlock($refMethod);
$docBlockComment = $docBlockObj->getSummary() . "\n" . $docBlockObj->getDescription()->render();

$deprecated = $docBlockObj->getTagsByName('deprecated');
if (count($deprecated) >= 1) {
$fieldDescriptor->setDeprecationReason(trim((string) $deprecated[0]));
}

$fieldDescriptor->setComment($docBlockComment);
$args = $this->mapParameters($refMethod->getParameters(), $docBlockObj, $sourceField);

Expand Down
6 changes: 5 additions & 1 deletion src/QueryField.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class QueryField extends FieldDefinition
* @param array<string, ParameterInterface> $prefetchArgs Indexed by argument name.
* @param array<string, mixed> $additionalConfig
*/
public function __construct(string $name, OutputType $type, array $arguments, ResolverInterface $originalResolver, callable $resolver, ?string $comment, ?string $prefetchMethodName, array $prefetchArgs, array $additionalConfig = [])
public function __construct(string $name, OutputType $type, array $arguments, ResolverInterface $originalResolver, callable $resolver, ?string $comment, ?string $deprecationReason, ?string $prefetchMethodName, array $prefetchArgs, array $additionalConfig = [])
{
$config = [
'name' => $name,
Expand All @@ -52,6 +52,9 @@ public function __construct(string $name, OutputType $type, array $arguments, Re
if ($comment) {
$config['description'] = $comment;
}
if ($deprecationReason) {
$config['deprecationReason'] = $deprecationReason;
}

$resolveFn = function ($source, array $args, $context, ResolveInfo $info) use ($arguments, $originalResolver, $resolver) {
if ($originalResolver instanceof SourceResolver || $originalResolver instanceof MagicPropertyResolver) {
Expand Down Expand Up @@ -209,6 +212,7 @@ private static function fromDescriptor(QueryFieldDescriptor $fieldDescriptor): s
$fieldDescriptor->getOriginalResolver(),
$fieldDescriptor->getResolver(),
$fieldDescriptor->getComment(),
$fieldDescriptor->getDeprecationReason(),
$fieldDescriptor->getPrefetchMethodName(),
$fieldDescriptor->getPrefetchParameters()
);
Expand Down
12 changes: 12 additions & 0 deletions src/QueryFieldDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class QueryFieldDescriptor
private $injectSource;
/** @var string|null */
private $comment;
/** @var string|null */
private $deprecationReason;
/** @var MiddlewareAnnotations */
private $middlewareAnnotations;
/** @var ReflectionMethod */
Expand Down Expand Up @@ -180,6 +182,16 @@ public function setComment(?string $comment): void
$this->comment = $comment;
}

public function getDeprecationReason(): ?string
{
return $this->deprecationReason;
}

public function setDeprecationReason(?string $deprecationReason): void
{
$this->deprecationReason = $deprecationReason;
}

public function getMiddlewareAnnotations(): MiddlewareAnnotations
{
return $this->middlewareAnnotations;
Expand Down
8 changes: 8 additions & 0 deletions tests/Fixtures/Integration/Models/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ public function getName()
return $this->name;
}

/**
* @deprecated use field `name`
*/
public function getDeprecatedName()
{
return $this->name;
}

public function getManager(): ?Contact
{
return $this->manager;
Expand Down
1 change: 1 addition & 0 deletions tests/Fixtures/Integration/Types/ContactType.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/**
* @ExtendType(class=Contact::class)
* @SourceField(name="name", phpType="string")
* @SourceField(name="deprecatedName", phpType="string")
* @SourceField(name="birthDate")
* @SourceField(name="manager")
* @SourceField(name="relations")
Expand Down
9 changes: 9 additions & 0 deletions tests/Fixtures/Integration/Types/ExtendedContactType.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ public function uppercaseName(Contact $contact): string
return strtoupper($contact->getName());
}

/**
* @Field()
* @deprecated use field `uppercaseName`
*/
public function deprecatedUppercaseName(Contact $contact): string
{
return strtoupper($contact->getName());
}

/**
* Here, we are testing overriding the field in the extend class.
*
Expand Down
95 changes: 95 additions & 0 deletions tests/Integration/EndToEndTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,101 @@ public function testEndToEnd(): void
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
}

public function testDeprecatedField(): void
{
/**
* @var Schema $schema
*/
$schema = $this->mainContainer->get(Schema::class);

$schema->assertValid();

$queryString = '
query {
contacts {
name
uppercaseName
deprecatedUppercaseName
deprecatedName
}
}
';

$result = GraphQL::executeQuery(
$schema,
$queryString,
null,
new Context()
);

$this->assertSame([
'contacts' => [
[
'name' => 'Joe',
'uppercaseName' => 'JOE',
'deprecatedUppercaseName' => 'JOE',
'deprecatedName' => 'Joe',
],
[
'name' => 'Bill',
'uppercaseName' => 'BILL',
'deprecatedUppercaseName' => 'BILL',
'deprecatedName' => 'Bill',
]

]
], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);

// Let's introspect to see if the field is marked as deprecated
// in the resulting GraphQL schema
$queryString = '
query deprecatedField {
__type(name: "Contact") {
fields(includeDeprecated: true) {
name
isDeprecated
deprecationReason
}
}
}
';

$result = GraphQL::executeQuery(
$schema,
$queryString,
null,
new Context()
);

$fields = $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']['__type']['fields'];
$deprecatedFields = [
'deprecatedUppercaseName',
'deprecatedName'
];
$fields = array_filter($fields, function($field) use ($deprecatedFields) {
if (in_array($field['name'], $deprecatedFields)) {
return true;
}
return false;
});
$this->assertCount(
count($deprecatedFields),
$fields,
'Missing deprecated fields on GraphQL Schema'
);
foreach ($fields as $field) {
$this->assertTrue(
$field['isDeprecated'],
'Field ' . $field['name'] . ' must be marked deprecated, but is not'
);
$this->assertStringContainsString(
'use field ',
$field['deprecationReason'],
'Field ' . $field['name'] . ' is misssing a deprecation reason'
);
}
}

public function testPrefetchException(): void
{
/**
Expand Down
2 changes: 1 addition & 1 deletion tests/QueryFieldTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function resolve(?object $source, array $args, $context, ResolveInfo $inf
{
throw new Error('boum');
}
} ], $sourceResolver, $sourceResolver, null, null, []);
} ], $sourceResolver, $sourceResolver, null, null, null, []);

$resolve = $queryField->resolveFn;

Expand Down

0 comments on commit 72ed388

Please sign in to comment.