From be46b144410676787e155130e551a53c8248fc28 Mon Sep 17 00:00:00 2001 From: Jeremiah VALERIE Date: Wed, 18 May 2016 15:36:45 +0200 Subject: [PATCH] Fix `ResolveInfo::getFieldSelection()` when using multiple fragments on the same field. --- src/Type/Definition/ResolveInfo.php | 9 +++-- tests/StarWarsQueryTest.php | 51 +++++++++++++++++++++++++++++ tests/StarWarsSchema.php | 15 +++++++-- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/Type/Definition/ResolveInfo.php b/src/Type/Definition/ResolveInfo.php index 1c60b5d..dcdc3ec 100644 --- a/src/Type/Definition/ResolveInfo.php +++ b/src/Type/Definition/ResolveInfo.php @@ -95,9 +95,14 @@ class ResolveInfo */ public function getFieldSelection($depth = 0) { + $fields = []; + /** @var Field $fieldAST */ - $fieldAST = $this->fieldASTs[0]; - return $this->foldSelectionSet($fieldAST->selectionSet, $depth); + foreach ($this->fieldASTs as $fieldAST) { + $fields = array_merge_recursive($fields, $this->foldSelectionSet($fieldAST->selectionSet, $depth)); + } + + return $fields; } private function foldSelectionSet(SelectionSet $selectionSet, $descend) diff --git a/tests/StarWarsQueryTest.php b/tests/StarWarsQueryTest.php index f8eb5e1..1eff3be 100644 --- a/tests/StarWarsQueryTest.php +++ b/tests/StarWarsQueryTest.php @@ -302,6 +302,57 @@ class StarWarsQueryTest extends \PHPUnit_Framework_TestCase $this->assertValidQuery($query, $expected); } + function testFragmentWithProjection() + { + $query = ' + query UseFragment { + human(id: "1003") { + name + ...fa + ...fb + } + } + + fragment fa on Character { + friends { + id + } + } + fragment fb on Character { + friends { + name + } + } + '; + + $expected = [ + 'human' => [ + 'name' => 'Leia Organa', + 'friends' => [ + [ + 'name' => 'Luke Skywalker', + 'id' => '1000' + + ], + [ + 'name' => 'Han Solo', + 'id' => '1002' + ], + [ + 'name' => 'C-3PO', + 'id' => '2000' + ], + [ + 'name' => 'R2-D2', + 'id' => '2001' + ] + ] + ] + ]; + + $this->assertValidQuery($query, $expected); + } + // Using __typename to find the type of an object public function testVerifyThatR2D2IsADroid() { diff --git a/tests/StarWarsSchema.php b/tests/StarWarsSchema.php index 351bb58..dc2a572 100644 --- a/tests/StarWarsSchema.php +++ b/tests/StarWarsSchema.php @@ -16,6 +16,7 @@ use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\NonNull; use GraphQL\Type\Definition\ObjectType; +use GraphQL\Type\Definition\ResolveInfo; use GraphQL\Type\Definition\Type; /** @@ -161,8 +162,18 @@ class StarWarsSchema 'friends' => [ 'type' => Type::listOf($characterInterface), 'description' => 'The friends of the human, or an empty list if they have none.', - 'resolve' => function ($human) { - return StarWarsData::getFriends($human); + 'resolve' => function ($human, $args, ResolveInfo $info) { + $fieldSelection = $info->getFieldSelection(); + $fieldSelection['id'] = true; + + $friends = array_map( + function($friend) use ($fieldSelection) { + return array_intersect_key($friend, $fieldSelection); + }, + StarWarsData::getFriends($human) + ); + + return $friends; }, ], 'appearsIn' => [