Skip to content

Commit 8b52961

Browse files
authored
Merge branch 'master' into patch-3
2 parents d269442 + 04818f2 commit 8b52961

File tree

16 files changed

+104
-25
lines changed

16 files changed

+104
-25
lines changed

docs/annotations/index.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,27 @@ In the previous example, the generated `resolve` config of the `something` field
116116

117117
## Type & Args auto-guessing
118118

119+
### @Field type auto-guessing when defined on a property with a type hint
120+
121+
The type of the `@Field` annotation can be auto-guessed if it's defined on a property with a type hint.
122+
If the property has a usable type hint this is used and no futher guessing is done.
123+
124+
For example:
125+
126+
```php
127+
/**
128+
* @GQL\Type
129+
*/
130+
class MyType {
131+
/**
132+
* @GQL\Field
133+
*/
134+
protected string $property;
135+
}
136+
```
137+
138+
In this example, the type `String!` will be auto-guessed from the type hint of the property.
139+
119140
### @Field type auto-guessing from Doctrine ORM Annotations
120141

121142
Based on other Doctrine annotations on your fields, the corresponding GraphQL type can sometimes be guessed automatically.

src/Annotation/Access.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class Access implements Annotation
1515
/**
1616
* Field access.
1717
*
18-
* @required
18+
* @Required
1919
*
2020
* @var string
2121
*/

src/Annotation/Arg.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class Arg implements Annotation
1515
/**
1616
* Argument name.
1717
*
18-
* @required
18+
* @Required
1919
*
2020
* @var string
2121
*/
@@ -31,7 +31,7 @@ final class Arg implements Annotation
3131
/**
3232
* Argument type.
3333
*
34-
* @required
34+
* @Required
3535
*
3636
* @var string
3737
*/

src/Annotation/Deprecated.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class Deprecated implements Annotation
1515
/**
1616
* The deprecation reason.
1717
*
18-
* @required
18+
* @Required
1919
*
2020
* @var string
2121
*/

src/Annotation/Description.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class Description implements Annotation
1515
/**
1616
* The object description.
1717
*
18-
* @required
18+
* @Required
1919
*
2020
* @var string
2121
*/

src/Annotation/Field.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ class Field implements Annotation
2222
/**
2323
* Field Type.
2424
*
25-
* @required
26-
*
2725
* @var string
2826
*/
2927
public string $type;

src/Annotation/FieldsBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class FieldsBuilder implements Annotation
1515
/**
1616
* Builder name.
1717
*
18-
* @required
18+
* @Required
1919
*
2020
* @var string
2121
*/

src/Annotation/IsPublic.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class IsPublic implements Annotation
1515
/**
1616
* Field publicity.
1717
*
18-
* @required
18+
* @Required
1919
*
2020
* @var string
2121
*/

src/Annotation/Relay/Edge.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ final class Edge extends Type
1717
/**
1818
* Edge Node type.
1919
*
20-
* @required
20+
* @Required
2121
*
2222
* @var string
2323
*/

src/Annotation/TypeInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class TypeInterface implements Annotation
2222
/**
2323
* Resolver type for interface.
2424
*
25-
* @required
25+
* @Required
2626
*
2727
* @var string
2828
*/

src/Config/Parser/AnnotationParser.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ private static function scalarAnnotationToGQLConfiguration(GraphClass $graphClas
408408
*/
409409
private static function enumAnnotationToGQLConfiguration(GraphClass $graphClass, GQL\Enum $enumAnnotation): array
410410
{
411-
$enumValues = $enumAnnotation->values ? $enumAnnotation->values : [];
411+
$enumValues = $enumAnnotation->values ?? [];
412412

413413
$values = [];
414414

@@ -585,7 +585,7 @@ private static function getTypeFieldConfigurationFromReflector(GraphClass $graph
585585
}
586586
} else {
587587
try {
588-
$fieldConfiguration['type'] = self::guessType($graphClass, $annotations);
588+
$fieldConfiguration['type'] = self::guessType($graphClass, $reflector, self::VALID_OUTPUT_TYPES);
589589
} catch (Exception $e) {
590590
throw new InvalidArgumentException(sprintf('The attribute "type" on "@%s" defined on "%s" is required and cannot be auto-guessed : %s.', $fieldAnnotationName, $reflector->getName(), $e->getMessage()));
591591
}
@@ -622,16 +622,29 @@ private static function getGraphQLInputFieldsFromAnnotations(GraphClass $graphCl
622622
foreach ($reflectors as $reflector) {
623623
$annotations = $graphClass->getAnnotations($reflector);
624624

625-
/** @var GQL\Field $fieldAnnotation */
625+
/** @var GQL\Field|null $fieldAnnotation */
626626
$fieldAnnotation = self::getFirstAnnotationMatching($annotations, GQL\Field::class);
627627

628+
// No field annotation found
629+
if (null === $fieldAnnotation) {
630+
continue;
631+
}
632+
628633
// Ignore field with resolver when the type is an Input
629634
if (isset($fieldAnnotation->resolve)) {
630635
continue;
631636
}
632637

633638
$fieldName = $reflector->getName();
634-
$fieldType = $fieldAnnotation->type;
639+
if (isset($fieldAnnotation->type)) {
640+
$fieldType = $fieldAnnotation->type;
641+
} else {
642+
try {
643+
$fieldType = self::guessType($graphClass, $reflector, self::VALID_INPUT_TYPES);
644+
} catch (Exception $e) {
645+
throw new InvalidArgumentException(sprintf('The attribute "type" on GraphQL annotation "@%s" is missing on property "%s" and cannot be auto-guessed as there is no type hint or Doctrine annotation.', GQL\Field::class, $reflector->getName()));
646+
}
647+
}
635648
$fieldConfiguration = [];
636649
if ($fieldType) {
637650
// Resolve a PHP class from a GraphQL type
@@ -729,7 +742,7 @@ private static function getGraphQLFieldsFromProviders(GraphClass $graphClass, st
729742
$currentValue = sprintf("service('%s')", self::formatNamespaceForExpression($providerMetadata->getName()));
730743
$providerFields = self::getGraphQLTypeFieldsFromAnnotations($graphClass, $methods, $expectedAnnotation, $currentValue);
731744
foreach ($providerFields as $fieldName => $fieldConfig) {
732-
if ($providerAnnotation->prefix) {
745+
if (isset($providerAnnotation->prefix)) {
733746
$fieldName = sprintf('%s%s', $providerAnnotation->prefix, $fieldName);
734747
}
735748

@@ -839,8 +852,17 @@ private static function suffixName(string $name, string $suffix): string
839852
*
840853
* @throws RuntimeException
841854
*/
842-
private static function guessType(GraphClass $graphClass, array $annotations): string
855+
private static function guessType(GraphClass $graphClass, ReflectionProperty $reflector, array $filterGraphQLTypes = []): string
843856
{
857+
if ($reflector->hasType()) {
858+
try {
859+
// @phpstan-ignore-next-line
860+
return self::resolveGraphQLTypeFromReflectionType($reflector->getType(), $filterGraphQLTypes);
861+
} catch (Exception $e) {
862+
}
863+
}
864+
865+
$annotations = $graphClass->getAnnotations($reflector);
844866
$columnAnnotation = self::getFirstAnnotationMatching($annotations, Column::class);
845867
if (null !== $columnAnnotation) {
846868
$type = self::resolveTypeFromDoctrineType($columnAnnotation->type);

tests/Config/Parser/AnnotationParserTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ public function testInput(): void
188188
'fields' => [
189189
'name' => ['type' => 'String!'],
190190
'population' => ['type' => 'Int!'],
191+
'description' => ['type' => 'String!'],
192+
'diameter' => ['type' => 'Int'],
193+
'variable' => ['type' => 'Int!'],
194+
'tags' => ['type' => '[String]!'],
191195
],
192196
]);
193197
}

tests/Config/Parser/fixtures/annotations/Input/Planet.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Overblog\GraphQLBundle\Tests\Config\Parser\fixtures\annotations\Input;
66

7+
use Doctrine\ORM\Mapping as ORM;
78
use Overblog\GraphQLBundle\Annotation as GQL;
89

910
/**
@@ -26,4 +27,31 @@ class Planet
2627
* @GQL\Field(type="Int!")
2728
*/
2829
protected string $population;
30+
31+
/**
32+
* @GQL\Field
33+
*/
34+
protected string $description;
35+
36+
/**
37+
* @GQL\Field
38+
* @ORM\Column(type="integer", nullable=true)
39+
*/
40+
// @phpstan-ignore-next-line
41+
protected $diameter;
42+
43+
/**
44+
* @GQL\Field
45+
* @ORM\Column(type="boolean")
46+
*/
47+
protected int $variable;
48+
49+
// @phpstan-ignore-next-line
50+
protected $dummy;
51+
52+
/**
53+
* @GQL\Field
54+
* @ORM\Column(type="text[]")
55+
*/
56+
protected array $tags;
2957
}

tests/Config/Parser/fixtures/annotations/Invalid/InvalidAccess.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
class InvalidAccess
1313
{
1414
/**
15-
* @GQL\Access()
15+
* @GQL\Access("access")
1616
*/
1717
protected string $field;
1818
}

tests/Config/Parser/fixtures/annotations/Type/Droid.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class Droid extends Character
1414
{
1515
/**
16-
* @GQL\Field(type="Int!")
16+
* @GQL\Field
1717
*/
1818
protected int $memory;
1919
}

tests/Config/Parser/fixtures/annotations/Type/Lightsaber.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,38 +23,44 @@ class Lightsaber
2323
* @ORM\Column(type="integer", nullable=true)
2424
* @GQL\Field
2525
*/
26-
protected int $size;
26+
// @phpstan-ignore-next-line
27+
protected $size;
2728

2829
/**
2930
* @ORM\OneToMany(targetEntity="Hero")
3031
* @GQL\Field
3132
*/
32-
protected Hero $holders;
33+
// @phpstan-ignore-next-line
34+
protected $holders;
3335

3436
/**
3537
* @ORM\ManyToOne(targetEntity="Hero")
3638
* @GQL\Field
3739
*/
38-
protected Hero $creator;
40+
// @phpstan-ignore-next-line
41+
protected $creator;
3942

4043
/**
4144
* @ORM\OneToOne(targetEntity="Crystal")
4245
* @GQL\Field
4346
*/
44-
protected Crystal $crystal;
47+
// @phpstan-ignore-next-line
48+
protected $crystal;
4549

4650
/**
4751
* @ORM\ManyToMany(targetEntity="Battle")
4852
* @GQL\Field
4953
*/
50-
protected Battle $battles;
54+
// @phpstan-ignore-next-line
55+
protected $battles;
5156

5257
/**
5358
* @GQL\Field
5459
* @ORM\OneToOne(targetEntity="Hero")
5560
* @ORM\JoinColumn(nullable=true)
5661
*/
57-
protected Hero $currentHolder;
62+
// @phpstan-ignore-next-line
63+
protected $currentHolder;
5864

5965
/**
6066
* @GQL\Field

0 commit comments

Comments
 (0)