Skip to content

Commit 65bf449

Browse files
committed
Entity without relations must not have an empty FilterGroupJoin
GraphQL does not allow to have type without any fields, so we must check that before outputing FilterGroupJoin. Fixes #22
1 parent ea111ae commit 65bf449

File tree

8 files changed

+74
-65
lines changed

8 files changed

+74
-65
lines changed

src/Factory/Type/FilterGroupJoinTypeFactory.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,16 @@ private function getJoinsFields(string $className): array
7777

7878
return $fields;
7979
}
80+
81+
/**
82+
* Return whether it is possible to create a valid type for join
83+
*
84+
* @param string $className
85+
*
86+
* @return bool
87+
*/
88+
public function canCreate(string $className): bool
89+
{
90+
return !empty($this->entityManager->getClassMetadata($className)->associationMappings);
91+
}
8092
}

src/Factory/Type/FilterTypeFactory.php

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,27 +75,32 @@ public function create(string $className, string $typeName): Type
7575
*/
7676
private function getGroupType(string $className, string $typeName): InputObjectType
7777
{
78+
$fields = [
79+
[
80+
'name' => 'groupLogic',
81+
'type' => $this->types->get('LogicalOperator'),
82+
'description' => 'The logic operator to be used to append this group',
83+
'defaultValue' => 'AND',
84+
],
85+
[
86+
'name' => 'conditionsLogic',
87+
'type' => $this->types->get('LogicalOperator'),
88+
'description' => 'The logic operator to be used within all conditions in this group',
89+
'defaultValue' => 'AND',
90+
],
91+
$this->filterGroupConditionTypeFactory->getField($className),
92+
];
93+
94+
// Only create join type, if there is anything to join on
95+
if ($this->filterGroupJoinTypeFactory->canCreate($className)) {
96+
$fields[] = $this->filterGroupJoinTypeFactory->getField($className);
97+
}
98+
7899
$conditionType = new InputObjectType([
79100
'name' => $typeName . 'Group',
80101
'description' => 'Specify a set of joins and conditions to filter `' . Utils::getTypeName($className) . '`',
81-
'fields' => [
82-
[
83-
'name' => 'groupLogic',
84-
'type' => $this->types->get('LogicalOperator'),
85-
'description' => 'The logic operator to be used to append this group',
86-
'defaultValue' => 'AND',
87-
],
88-
[
89-
'name' => 'conditionsLogic',
90-
'type' => $this->types->get('LogicalOperator'),
91-
'description' => 'The logic operator to be used within all conditions in this group',
92-
'defaultValue' => 'AND',
93-
],
94-
$this->filterGroupJoinTypeFactory->getField($className),
95-
$this->filterGroupConditionTypeFactory->getField($className),
96-
],
102+
'fields' => $fields,
97103
]);
98-
99104
$this->types->registerInstance($conditionType);
100105

101106
return $conditionType;

tests/FilterTypesTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function testCanGetPostFilter(): void
2020
$this->assertAllTypes('tests/data/PostFilter.graphqls', $actual);
2121
}
2222

23-
public function testCanInheritSortingFromTraits(): void
23+
public function testCanInheritFilterFromTraits(): void
2424
{
2525
$actual = $this->types->getFilter(ModelWithTraits::class);
2626
$this->assertAllTypes('tests/data/ModelWithTraitsFilter.graphqls', $actual);

tests/TypesTrait.php

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
use DateTime;
88
use GraphQL\Doctrine\Types;
99
use GraphQL\Type\Definition\BooleanType;
10+
use GraphQL\Type\Definition\InputType;
1011
use GraphQL\Type\Definition\ObjectType;
1112
use GraphQL\Type\Definition\OutputType;
1213
use GraphQL\Type\Definition\Type;
14+
use GraphQL\Type\Definition\WrappingType;
1315
use GraphQL\Type\Schema;
1416
use GraphQL\Utils\SchemaPrinter;
1517
use GraphQLTests\Doctrine\Blog\Types\CustomType;
@@ -72,29 +74,39 @@ private function assertAllTypes(string $expectedFile, Type $type): void
7274
*/
7375
private function getSchemaForType(Type $type): Schema
7476
{
75-
if ($type instanceof OutputType) {
76-
$config = [
77-
'query' => new ObjectType([
78-
'name' => 'query',
79-
'fields' => [
80-
'defaultField' => $type,
81-
],
82-
]),
83-
];
77+
if ($type instanceof WrappingType) {
78+
$wrappedType = $type->getWrappedType(true);
8479
} else {
85-
$config = [
86-
'query' => new ObjectType([
87-
'name' => 'query',
88-
]),
89-
'mutation' => new ObjectType([
90-
'name' => 'mutation',
91-
'fields' => [
92-
'defaultField' => $type,
93-
],
94-
]),
80+
$wrappedType = $type;
81+
}
82+
83+
if ($wrappedType instanceof OutputType) {
84+
$outputType = $type;
85+
$args = [];
86+
} elseif ($wrappedType instanceof InputType) {
87+
$outputType = Type::boolean();
88+
$args = [
89+
'defaultArg' => $type,
9590
];
91+
} else {
92+
throw new \Exception('Unsupported type: ' . get_class($wrappedType));
9693
}
9794

98-
return new Schema($config);
95+
$config = [
96+
'query' => new ObjectType([
97+
'name' => 'query',
98+
'fields' => [
99+
'defaultField' => [
100+
'type' => $outputType,
101+
'args' => $args,
102+
],
103+
],
104+
]),
105+
];
106+
107+
$schema = new Schema($config);
108+
$schema->assertValid();
109+
110+
return $schema;
99111
}
100112
}

tests/data/ModelWithTraitsFilter.graphqls

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
schema {
22
query: query
3-
mutation: mutation
43
}
54

65
input BetweenOperatorID {
@@ -74,11 +73,6 @@ input ModelWithTraitsFilterGroup {
7473
"""The logic operator to be used within all conditions in this group"""
7574
conditionsLogic: LogicalOperator = AND
7675

77-
"""
78-
Optional joins to either filter the query or fetch related objects from DB in a single query
79-
"""
80-
joins: ModelWithTraitsFilterGroupJoin
81-
8276
"""Conditions to be applied on fields"""
8377
conditions: [ModelWithTraitsFilterGroupCondition!]
8478
}
@@ -108,11 +102,6 @@ input ModelWithTraitsFilterGroupConditionId {
108102
group: GroupOperatorID
109103
}
110104

111-
"""Type to specify join tables in a filter"""
112-
input ModelWithTraitsFilterGroupJoin {
113-
114-
}
115-
116105
input NullOperatorID {
117106
not: Boolean = false
118107
}
@@ -121,10 +110,6 @@ input SearchOperatorString {
121110
term: String!
122111
}
123112

124-
type mutation {
125-
defaultField: ModelWithTraitsFilter
126-
}
127-
128113
type query {
129-
114+
defaultField(defaultArg: ModelWithTraitsFilter): Boolean
130115
}

tests/data/ModelWithTraitsSorting.graphqls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ enum SortingOrder {
2020
}
2121

2222
type query {
23-
defaultField: [ModelWithTraitsSorting!]
23+
defaultField(defaultArg: [ModelWithTraitsSorting!]): Boolean
2424
}

tests/data/PostFilter.graphqls

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
schema {
22
query: query
3-
mutation: mutation
43
}
54

65
input BetweenOperatorBoolean {
@@ -299,13 +298,13 @@ input PostFilterGroup {
299298
"""The logic operator to be used within all conditions in this group"""
300299
conditionsLogic: LogicalOperator = AND
301300

301+
"""Conditions to be applied on fields"""
302+
conditions: [PostFilterGroupCondition!]
303+
302304
"""
303305
Optional joins to either filter the query or fetch related objects from DB in a single query
304306
"""
305307
joins: PostFilterGroupJoin
306-
307-
"""Conditions to be applied on fields"""
308-
conditions: [PostFilterGroupCondition!]
309308
}
310309

311310
"""Type to specify conditions on fields"""
@@ -560,10 +559,6 @@ input UserFilterGroupJoin {
560559
manager: JoinOnUser
561560
}
562561

563-
type mutation {
564-
defaultField: PostFilter
565-
}
566-
567562
type query {
568-
563+
defaultField(defaultArg: PostFilter): Boolean
569564
}

tests/data/PostSorting.graphqls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ enum SortingOrder {
2626
}
2727

2828
type query {
29-
defaultField: [PostSorting!]
29+
defaultField(defaultArg: [PostSorting!]): Boolean
3030
}

0 commit comments

Comments
 (0)