18
18
* name?: string|null,
19
19
* description?: string|null,
20
20
* fields: iterable<FieldConfig>|callable(): iterable<FieldConfig>,
21
+ * isOneOf?: bool|null,
21
22
* parseValue?: callable(array<string, mixed>): mixed,
22
23
* astNode?: InputObjectTypeDefinitionNode|null,
23
24
* extensionASTNodes?: array<InputObjectTypeExtensionNode>|null
@@ -35,6 +36,8 @@ class InputObjectType extends Type implements InputType, NullableType, NamedType
35
36
/** @phpstan-var InputObjectConfig */
36
37
public array $ config ;
37
38
39
+ public bool $ isOneOf ;
40
+
38
41
/**
39
42
* Lazily initialized.
40
43
*
@@ -55,6 +58,7 @@ public function __construct(array $config)
55
58
$ this ->description = $ config ['description ' ] ?? null ;
56
59
$ this ->astNode = $ config ['astNode ' ] ?? null ;
57
60
$ this ->extensionASTNodes = $ config ['extensionASTNodes ' ] ?? [];
61
+ $ this ->isOneOf = $ config ['isOneOf ' ] ?? false ;
58
62
59
63
$ this ->config = $ config ;
60
64
}
@@ -91,6 +95,12 @@ public function hasField(string $name): bool
91
95
return isset ($ this ->fields [$ name ]);
92
96
}
93
97
98
+ /** Returns true if this is a oneOf input object type. */
99
+ public function isOneOf (): bool
100
+ {
101
+ return $ this ->isOneOf ;
102
+ }
103
+
94
104
/**
95
105
* @throws InvariantViolation
96
106
*
@@ -196,6 +206,44 @@ public function assertValid(): void
196
206
foreach ($ resolvedFields as $ field ) {
197
207
$ field ->assertValid ($ this );
198
208
}
209
+
210
+ // Additional validation for oneOf input objects
211
+ if ($ this ->isOneOf ()) {
212
+ $ this ->validateOneOfConstraints ($ resolvedFields );
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Validates that oneOf input object constraints are met.
218
+ *
219
+ * @param array<string, InputObjectField> $fields
220
+ *
221
+ * @throws InvariantViolation
222
+ */
223
+ private function validateOneOfConstraints (array $ fields ): void
224
+ {
225
+ if (count ($ fields ) === 0 ) {
226
+ throw new InvariantViolation ("OneOf input object type {$ this ->name } must define one or more fields. " );
227
+ }
228
+
229
+ foreach ($ fields as $ fieldName => $ field ) {
230
+ $ fieldType = $ field ->getType ();
231
+
232
+ // OneOf fields must be nullable (not wrapped in NonNull)
233
+ if ($ fieldType instanceof NonNull) {
234
+ throw new InvariantViolation ("OneOf input object type {$ this ->name } field {$ fieldName } must be nullable. " );
235
+ }
236
+
237
+ // OneOf fields cannot have default values
238
+ if ($ field ->defaultValueExists ()) {
239
+ throw new InvariantViolation ("OneOf input object type {$ this ->name } field {$ fieldName } cannot have a default value. " );
240
+ }
241
+
242
+ // OneOf fields cannot be deprecated (optional constraint for now)
243
+ if ($ field ->isDeprecated ()) {
244
+ throw new InvariantViolation ("OneOf input object type {$ this ->name } field {$ fieldName } cannot be deprecated. " );
245
+ }
246
+ }
199
247
}
200
248
201
249
public function astNode (): ?InputObjectTypeDefinitionNode
0 commit comments