Skip to content

Commit

Permalink
fix(graphql): type builder output (api-platform#4791)
Browse files Browse the repository at this point in the history
* Revert "fix(graphql): output creates its own type in TypeBuilder (api-platform#4766)"

This reverts commit 1f4085e.

* fix: resources order
  • Loading branch information
soyuka committed Jun 29, 2022
1 parent 5b63577 commit 3cfb459
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 118 deletions.
20 changes: 0 additions & 20 deletions features/graphql/mutation.feature
Original file line number Diff line number Diff line change
Expand Up @@ -819,26 +819,6 @@ Feature: GraphQL mutation support
And the JSON node "data.testCustomArgumentsDummyCustomMutation.dummyCustomMutation.result" should be equal to "18"
And the JSON node "data.testCustomArgumentsDummyCustomMutation.clientMutationId" should be equal to "myId"

Scenario: Execute a custom mutation with output
When I send the following GraphQL request:
"""
mutation {
testOutputDummyCustomMutation(input: {id: "/dummy_custom_mutations/1", operandA: 9, clientMutationId: "myId"}) {
dummyCustomMutation {
baz
bat
}
clientMutationId
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON node "data.testOutputDummyCustomMutation.dummyCustomMutation.baz" should be equal to "98"
And the JSON node "data.testOutputDummyCustomMutation.dummyCustomMutation.bat" should be equal to "9"
And the JSON node "data.testOutputDummyCustomMutation.clientMutationId" should be equal to "myId"

Scenario: Uploading a file with a custom mutation
Given I have the following file for a GraphQL request:
| name | file |
Expand Down
26 changes: 0 additions & 26 deletions features/graphql/query.feature
Original file line number Diff line number Diff line change
Expand Up @@ -432,32 +432,6 @@ Feature: GraphQL query support
}
"""

Scenario: Custom item query with output
Given there are 2 dummyCustomQuery objects
When I send the following GraphQL request:
"""
{
testItemOutputDummyCustomQuery(id: "/dummy_custom_queries/1",) {
baz
bat
}
}
"""
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON should be equal to:
"""
{
"data": {
"testItemOutputDummyCustomQuery": {
"baz": 46,
"bat": "Success!"
}
}
}
"""

@createSchema
Scenario: Retrieve an item with different serialization groups for item_query and collection_query
Given there are 1 dummy with different GraphQL serialization groups objects
Expand Down
11 changes: 5 additions & 6 deletions src/GraphQl/Type/TypeBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ public function getResourceObjectType(?string $resourceClass, ResourceMetadataCo
$shortName = $operation->getShortName();
$operationName = $operation->getName();

$ioMetadata = $input ? $operation->getInput() : $operation->getOutput();
if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null !== $ioMetadata['class']) {
$resourceClass = $ioMetadata['class'];
$shortName = $ioMetadata['name'] ?? $shortName;
}

if ($operation instanceof Mutation) {
$shortName = $operationName.ucfirst($shortName);
}
Expand Down Expand Up @@ -108,6 +102,11 @@ public function getResourceObjectType(?string $resourceClass, ResourceMetadataCo
return $resourceObjectType;
}

$ioMetadata = $input ? $operation->getInput() : $operation->getOutput();
if (null !== $ioMetadata && \array_key_exists('class', $ioMetadata) && null !== $ioMetadata['class']) {
$resourceClass = $ioMetadata['class'];
}

$wrapData = !$wrapped && ($operation instanceof Mutation || $operation instanceof Subscription) && !$input && $depth < 1;

$configuration = [
Expand Down
6 changes: 5 additions & 1 deletion src/Util/ReflectionClassRecursiveIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ public static function getReflectionClassesFromDirectories(array $directories):
}
}

$declared = array_merge(get_declared_classes(), get_declared_interfaces());
$sortedClasses = get_declared_classes();
sort($sortedClasses);
$sortedInterfaces = get_declared_interfaces();
sort($sortedInterfaces);
$declared = array_merge($sortedClasses, $sortedInterfaces);
foreach ($declared as $className) {
$reflectionClass = new \ReflectionClass($className);
$sourceFile = $reflectionClass->getFileName();
Expand Down
78 changes: 63 additions & 15 deletions tests/Fixtures/TestBundle/Document/DummyCustomMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,79 @@

namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GraphQl\Mutation;
use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
* Dummy with a custom GraphQL mutation resolver.
*
* @ODM\Document
* @ApiResource(graphql={
* "sum"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}}
* },
* "sumNotPersisted"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}}
* },
* "sumNoWriteCustomResult"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}},
* "write"=false
* },
* "sumOnlyPersist"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist_document",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}},
* "read"=false,
* "deserialize"=false,
* "validate"=false,
* "serialize"=false
* },
* "testCustomArguments"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom",
* "args"={"operandC"={"type"="Int!"}}
* }
* })
*
* @author Raoul Clais <[email protected]>
*/
#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist_document', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])]
#[ODM\Document]
class DummyCustomMutation
{
#[ODM\Id(strategy: 'INCREMENT', type: 'int')]
private ?int $id = null;
#[ODM\Field(type: 'int')]
private ?int $operandA = null;
#[Groups(['sum'])]
#[ODM\Field(type: 'int', nullable: true)]
private ?int $operandB = null;
#[Groups(['result'])]
#[ODM\Field(type: 'int', nullable: true)]
private ?int $result = null;
/**
* @var int|null
*
* @ODM\Id(strategy="INCREMENT", type="int")
*/
private $id;

/**
* @var int|null
*
* @ODM\Field(type="int")
*/
private $operandA;

/**
* @var int|null
*
* @Groups({"sum"})
* @ODM\Field(type="int", nullable=true)
*/
private $operandB;

/**
* @var int|null
*
* @Groups({"result"})
* @ODM\Field(type="int", nullable=true)
*/
private $result;

public function getId(): ?int
{
Expand Down
55 changes: 48 additions & 7 deletions tests/Fixtures/TestBundle/Document/DummyCustomQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,71 @@

namespace ApiPlatform\Tests\Fixtures\TestBundle\Document;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GraphQl\Query;
use ApiPlatform\Metadata\GraphQl\QueryCollection;
use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
* Dummy with custom GraphQL query resolvers.
*
* @author Lukas Lücke <[email protected]>
*
* @ApiResource(graphql={
* "testItem"={
* "item_query"="app.graphql.query_resolver.dummy_custom_item"
* },
* "testNotRetrievedItem"={
* "item_query"="app.graphql.query_resolver.dummy_custom_not_retrieved_item_document",
* "args"={}
* },
* "testNoReadAndSerializeItem"={
* "item_query"="app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document",
* "read"=false,
* "serialize"=false
* },
* "testItemCustomArguments"={
* "item_query"="app.graphql.query_resolver.dummy_custom_item",
* "args"={
* "id"={"type"="ID"},
* "customArgumentNullableBool"={"type"="Boolean"},
* "customArgumentBool"={"type"="Boolean!"},
* "customArgumentInt"={"type"="Int!"},
* "customArgumentString"={"type"="String!"},
* "customArgumentFloat"={"type"="Float!"},
* "customArgumentIntArray"={"type"="[Int!]!"},
* "customArgumentCustomType"={"type"="DateTime!"}
* }
* },
* "testCollection"={
* "collection_query"="app.graphql.query_resolver.dummy_custom_collection"
* },
* "testCollectionNoReadAndSerialize"={
* "collection_query"="app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize",
* "read"=false,
* "serialize"=false
* },
* "testCollectionCustomArguments"={
* "collection_query"="app.graphql.query_resolver.dummy_custom_collection",
* "args"={
* "customArgumentString"={"type"="String!"}
* }
* }
* })
* @ODM\Document
*/
#[ApiResource(graphQlOperations: [new Query(name: 'testItem', resolver: 'app.graphql.query_resolver.dummy_custom_item'), new Query(name: 'testNotRetrievedItem', resolver: 'app.graphql.query_resolver.dummy_custom_not_retrieved_item_document', args: []), new Query(name: 'testNoReadAndSerializeItem', resolver: 'app.graphql.query_resolver.dummy_custom_item_no_read_and_serialize_document', read: false, serialize: false), new Query(name: 'testItemCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_item', args: ['id' => ['type' => 'ID'], 'customArgumentNullableBool' => ['type' => 'Boolean'], 'customArgumentBool' => ['type' => 'Boolean!'], 'customArgumentInt' => ['type' => 'Int!'], 'customArgumentString' => ['type' => 'String!'], 'customArgumentFloat' => ['type' => 'Float!'], 'customArgumentIntArray' => ['type' => '[Int!]!'], 'customArgumentCustomType' => ['type' => 'DateTime!']]), new Query(name: 'testItemOutput', resolver: 'app.graphql.query_resolver.dummy_custom_item', output: OutputDto::class), new QueryCollection(name: 'testCollection', resolver: 'app.graphql.query_resolver.dummy_custom_collection'), new QueryCollection(name: 'testCollectionNoReadAndSerialize', resolver: 'app.graphql.query_resolver.dummy_custom_collection_no_read_and_serialize', read: false, serialize: false), new QueryCollection(name: 'testCollectionCustomArguments', resolver: 'app.graphql.query_resolver.dummy_custom_collection', args: ['customArgumentString' => ['type' => 'String!']])])]
#[ODM\Document]
class DummyCustomQuery
{
/**
* @var int
*
* @ODM\Id(strategy="INCREMENT", type="int")
*/
#[ODM\Id(strategy: 'INCREMENT', type: 'int')]
public $id;

/**
* @var string
*/
public $message;

/**
* @var array
*/
Expand Down
82 changes: 65 additions & 17 deletions tests/Fixtures/TestBundle/Entity/DummyCustomMutation.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,81 @@

namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GraphQl\Mutation;
use ApiPlatform\Tests\Fixtures\TestBundle\Dto\OutputDto;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
* Dummy with a custom GraphQL mutation resolver.
*
* @ORM\Entity
* @ApiResource(graphql={
* "sum"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}}
* },
* "sumNotPersisted"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom_not_persisted",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}}
* },
* "sumNoWriteCustomResult"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom_no_write_custom_result",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}},
* "write"=false
* },
* "sumOnlyPersist"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom_only_persist",
* "normalization_context"={"groups"={"result"}},
* "denormalization_context"={"groups"={"sum"}},
* "read"=false,
* "deserialize"=false,
* "validate"=false,
* "serialize"=false
* },
* "testCustomArguments"={
* "mutation"="app.graphql.mutation_resolver.dummy_custom",
* "args"={"operandC"={"type"="Int!"}}
* }
* })
*
* @author Raoul Clais <[email protected]>
*/
#[ApiResource(graphQlOperations: [new Mutation(name: 'sum', resolver: 'app.graphql.mutation_resolver.dummy_custom', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNotPersisted', resolver: 'app.graphql.mutation_resolver.dummy_custom_not_persisted', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']]), new Mutation(name: 'sumNoWriteCustomResult', resolver: 'app.graphql.mutation_resolver.dummy_custom_no_write_custom_result', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], write: false), new Mutation(name: 'sumOnlyPersist', resolver: 'app.graphql.mutation_resolver.dummy_custom_only_persist', normalizationContext: ['groups' => ['result']], denormalizationContext: ['groups' => ['sum']], read: false, deserialize: false, validate: false, serialize: false), new Mutation(name: 'testCustomArguments', resolver: 'app.graphql.mutation_resolver.dummy_custom', args: ['operandC' => ['type' => 'Int!']]), new Mutation(name: 'testOutput', resolver: 'app.graphql.mutation_resolver.dummy_custom', output: OutputDto::class)])]
#[ORM\Entity]
class DummyCustomMutation
{
#[ORM\Column(type: 'integer')]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'AUTO')]
private ?int $id = null;
#[ORM\Column(type: 'integer', nullable: true)]
private ?int $operandA = null;
#[Groups(['sum'])]
#[ORM\Column(type: 'integer', nullable: true)]
private ?int $operandB = null;
#[Groups(['result'])]
#[ORM\Column(type: 'integer', nullable: true)]
private ?int $result = null;
/**
* @var int|null
*
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

/**
* @var int|null
*
* @ORM\Column(type="integer", nullable=true)
*/
private $operandA;

/**
* @var int|null
*
* @Groups({"sum"})
* @ORM\Column(type="integer", nullable=true)
*/
private $operandB;

/**
* @var int|null
*
* @Groups({"result"})
* @ORM\Column(type="integer", nullable=true)
*/
private $result;

public function getId(): ?int
{
Expand Down
Loading

0 comments on commit 3cfb459

Please sign in to comment.