Skip to content

Commit 5e182bf

Browse files
authored
Merge pull request #39 from moufmouf/override
Optimization: we are not recreating fields in child class that are part of parent class
2 parents ab0e5cb + 06492d5 commit 5e182bf

File tree

7 files changed

+67
-2
lines changed

7 files changed

+67
-2
lines changed

src/FieldsBuilder.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace TheCodingMachine\GraphQLite;
55

66
use function array_merge;
7+
use function get_parent_class;
78
use GraphQL\Type\Definition\InputType;
89
use GraphQL\Type\Definition\ListOfType;
910
use GraphQL\Type\Definition\NonNull;
@@ -15,6 +16,7 @@
1516
use phpDocumentor\Reflection\Types\Self_;
1617
use Psr\Http\Message\UploadedFileInterface;
1718
use ReflectionMethod;
19+
use TheCodingMachine\GraphQLite\Annotations\Field;
1820
use TheCodingMachine\GraphQLite\Annotations\SourceFieldInterface;
1921
use TheCodingMachine\GraphQLite\Hydrators\HydratorInterface;
2022
use TheCodingMachine\GraphQLite\Mappers\CannotMapTypeExceptionInterface;
@@ -222,7 +224,21 @@ private function getFieldsByAnnotations($controller, string $annotationName, boo
222224
$oldDeclaringClass = null;
223225
$context = null;
224226

227+
$closestMatchingTypeClass = null;
228+
if ($annotationName === Field::class) {
229+
$parent = get_parent_class($refClass->getName());
230+
if ($parent !== null) {
231+
$closestMatchingTypeClass = $this->typeMapper->findClosestMatchingParent($parent);
232+
}
233+
}
234+
225235
foreach ($refClass->getMethods() as $refMethod) {
236+
if ($closestMatchingTypeClass !== null && $closestMatchingTypeClass === $refMethod->getDeclaringClass()->getName()) {
237+
// Optimisation: no need to fetch annotations from parent classes that are ALREADY GraphQL types.
238+
// We will merge the fields anyway.
239+
break;
240+
}
241+
226242
// First, let's check the "Query" or "Mutation" or "Field" annotation
227243
$queryAnnotation = $this->annotationReader->getRequestAnnotation($refMethod, $annotationName);
228244

src/Mappers/RecursiveTypeMapper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public function mapClassToType(string $className, ?OutputType $subType): Mutable
148148
* @param string $className
149149
* @return string|null
150150
*/
151-
private function findClosestMatchingParent(string $className): ?string
151+
public function findClosestMatchingParent(string $className): ?string
152152
{
153153
do {
154154
if ($this->typeMapper->canMapClassToType($className)) {

src/Mappers/RecursiveTypeMapperInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,12 @@ public function canMapNameToType(string $typeName): bool;
9494
* @return Type&(InputType|OutputType)
9595
*/
9696
public function mapNameToType(string $typeName): Type;
97+
98+
/**
99+
* Returns the closest parent that can be mapped, or null if nothing can be matched.
100+
*
101+
* @param string $className
102+
* @return string|null
103+
*/
104+
public function findClosestMatchingParent(string $className): ?string;
97105
}

src/Types/TypeAnnotatedObjectType.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public static function createFromAnnotatedClass(string $typeName, string $classN
4343
$fields = $fieldProvider->getSelfFields($className);
4444
}
4545
if ($parentType !== null) {
46+
// Note: with +=, the keys already present are not overloaded
4647
$fields += $parentType->getFields();
4748
}
4849
return $fields;

tests/Fixtures/Integration/Models/Contact.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use DateTimeInterface;
88
use Psr\Http\Message\UploadedFileInterface;
9+
use TheCodingMachine\GraphQLite\Annotations\Field;
910
use TheCodingMachine\GraphQLite\Annotations\Type;
1011

1112
/**
@@ -33,6 +34,10 @@ class Contact
3334
* @var DateTimeInterface
3435
*/
3536
private $birthDate;
37+
/**
38+
* @var string
39+
*/
40+
private $company;
3641

3742
public function __construct(string $name)
3843
{
@@ -107,4 +112,23 @@ public function setBirthDate(DateTimeInterface $birthDate): void
107112
{
108113
$this->birthDate = $birthDate;
109114
}
115+
116+
/**
117+
* This getter will be overridden in the extend class.
118+
*
119+
* @Field()
120+
* @return string
121+
*/
122+
public function getCompany(): string
123+
{
124+
return $this->company;
125+
}
126+
127+
/**
128+
* @param string $company
129+
*/
130+
public function setCompany(string $company): void
131+
{
132+
$this->company = $company;
133+
}
110134
}

tests/Fixtures/Integration/Types/ExtendedContactType.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,15 @@ public function uppercaseName(Contact $contact): string
2222
{
2323
return strtoupper($contact->getName());
2424
}
25-
}
25+
26+
/**
27+
* Here, we are testing overriding the field in the extend class.
28+
*
29+
* @Field()
30+
* @return string
31+
*/
32+
public function company(Contact $contact): string
33+
{
34+
return $contact->getName().' Ltd';
35+
}
36+
}

tests/Integration/EndToEndTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ public function testEndToEnd()
199199
query {
200200
contacts {
201201
name
202+
company
202203
uppercaseName
203204
... on User {
204205
email
@@ -216,10 +217,12 @@ public function testEndToEnd()
216217
'contacts' => [
217218
[
218219
'name' => 'Joe',
220+
'company' => 'Joe Ltd',
219221
'uppercaseName' => 'JOE'
220222
],
221223
[
222224
'name' => 'Bill',
225+
'company' => 'Bill Ltd',
223226
'uppercaseName' => 'BILL',
224227
'email' => 'bill@example.com'
225228
]
@@ -237,10 +240,12 @@ public function testEndToEnd()
237240
'contacts' => [
238241
[
239242
'name' => 'Joe',
243+
'company' => 'Joe Ltd',
240244
'uppercaseName' => 'JOE'
241245
],
242246
[
243247
'name' => 'Bill',
248+
'company' => 'Bill Ltd',
244249
'uppercaseName' => 'BILL',
245250
'email' => 'bill@example.com'
246251
]

0 commit comments

Comments
 (0)