@@ -67,48 +67,9 @@ public static function getVariableValues(Schema $schema, $varDefNodes, array $in
67
67
/** @var InputType|Type $varType */
68
68
$ varType = TypeInfo::typeFromAST ($ schema , $ varDefNode ->type );
69
69
70
- if (Type::isInputType ($ varType )) {
71
- if (array_key_exists ($ varName , $ inputs )) {
72
- $ value = $ inputs [$ varName ];
73
- $ coerced = Value::coerceValue ($ value , $ varType , $ varDefNode );
74
- /** @var Error[] $coercionErrors */
75
- $ coercionErrors = $ coerced ['errors ' ];
76
- if (empty ($ coercionErrors )) {
77
- $ coercedValues [$ varName ] = $ coerced ['value ' ];
78
- } else {
79
- $ messagePrelude = sprintf (
80
- 'Variable "$%s" got invalid value %s; ' ,
81
- $ varName ,
82
- Utils::printSafeJson ($ value )
83
- );
84
-
85
- foreach ($ coercionErrors as $ error ) {
86
- $ errors [] = new Error (
87
- $ messagePrelude . $ error ->getMessage (),
88
- $ error ->getNodes (),
89
- $ error ->getSource (),
90
- $ error ->getPositions (),
91
- $ error ->getPath (),
92
- $ error ,
93
- $ error ->getExtensions ()
94
- );
95
- }
96
- }
97
- } else {
98
- if ($ varType instanceof NonNull) {
99
- $ errors [] = new Error (
100
- sprintf (
101
- 'Variable "$%s" of required type "%s" was not provided. ' ,
102
- $ varName ,
103
- $ varType
104
- ),
105
- [$ varDefNode ]
106
- );
107
- } elseif ($ varDefNode ->defaultValue !== null ) {
108
- $ coercedValues [$ varName ] = AST ::valueFromAST ($ varDefNode ->defaultValue , $ varType );
109
- }
110
- }
111
- } else {
70
+ if (! Type::isInputType ($ varType )) {
71
+ // Must use input types for variables. This should be caught during
72
+ // validation, however is checked again here for safety.
112
73
$ errors [] = new Error (
113
74
sprintf (
114
75
'Variable "$%s" expected value of type "%s" which cannot be used as an input type. ' ,
@@ -117,6 +78,61 @@ public static function getVariableValues(Schema $schema, $varDefNodes, array $in
117
78
),
118
79
[$ varDefNode ->type ]
119
80
);
81
+ } else {
82
+ $ hasValue = array_key_exists ($ varName , $ inputs );
83
+ $ value = $ hasValue ? $ inputs [$ varName ] : Utils::undefined ();
84
+
85
+ if (! $ hasValue && $ varDefNode ->defaultValue ) {
86
+ // If no value was provided to a variable with a default value,
87
+ // use the default value.
88
+ $ coercedValues [$ varName ] = AST ::valueFromAST ($ varDefNode ->defaultValue , $ varType );
89
+ } elseif ((! $ hasValue || $ value === null ) && ($ varType instanceof NonNull)) {
90
+ // If no value or a nullish value was provided to a variable with a
91
+ // non-null type (required), produce an error.
92
+ $ errors [] = new Error (
93
+ sprintf (
94
+ $ hasValue
95
+ ? 'Variable "$%s" of non-null type "%s" must not be null. '
96
+ : 'Variable "$%s" of required type "%s" was not provided. ' ,
97
+ $ varName ,
98
+ Utils::printSafe ($ varType )
99
+ ),
100
+ [$ varDefNode ]
101
+ );
102
+ } elseif ($ hasValue ) {
103
+ if ($ value === null ) {
104
+ // If the explicit value `null` was provided, an entry in the coerced
105
+ // values must exist as the value `null`.
106
+ $ coercedValues [$ varName ] = null ;
107
+ } else {
108
+ // Otherwise, a non-null value was provided, coerce it to the expected
109
+ // type or report an error if coercion fails.
110
+ $ coerced = Value::coerceValue ($ value , $ varType , $ varDefNode );
111
+ /** @var Error[] $coercionErrors */
112
+ $ coercionErrors = $ coerced ['errors ' ];
113
+ if ($ coercionErrors ) {
114
+ $ messagePrelude = sprintf (
115
+ 'Variable "$%s" got invalid value %s; ' ,
116
+ $ varName ,
117
+ Utils::printSafeJson ($ value )
118
+ );
119
+
120
+ foreach ($ coercionErrors as $ error ) {
121
+ $ errors [] = new Error (
122
+ $ messagePrelude . $ error ->getMessage (),
123
+ $ error ->getNodes (),
124
+ $ error ->getSource (),
125
+ $ error ->getPositions (),
126
+ $ error ->getPath (),
127
+ $ error ,
128
+ $ error ->getExtensions ()
129
+ );
130
+ }
131
+ } else {
132
+ $ coercedValues [$ varName ] = $ coerced ['value ' ];
133
+ }
134
+ }
135
+ }
120
136
}
121
137
}
122
138
@@ -208,47 +224,71 @@ public static function getArgumentValuesForMap($fieldDefinition, $argumentValueM
208
224
$ argType = $ argumentDefinition ->getType ();
209
225
$ argumentValueNode = $ argumentValueMap [$ name ] ?? null ;
210
226
211
- if ($ argumentValueNode === null ) {
212
- if ($ argumentDefinition ->defaultValueExists ()) {
213
- $ coercedValues [$ name ] = $ argumentDefinition ->defaultValue ;
214
- } elseif ($ argType instanceof NonNull) {
227
+ if ($ argumentValueNode instanceof VariableNode) {
228
+ $ variableName = $ argumentValueNode ->name ->value ;
229
+ $ hasValue = $ variableValues ? array_key_exists ($ variableName , $ variableValues ) : false ;
230
+ $ isNull = $ hasValue ? $ variableValues [$ variableName ] === null : false ;
231
+ } else {
232
+ $ hasValue = $ argumentValueNode !== null ;
233
+ $ isNull = $ argumentValueNode instanceof NullValueNode;
234
+ }
235
+
236
+ if (! $ hasValue && $ argumentDefinition ->defaultValueExists ()) {
237
+ // If no argument was provided where the definition has a default value,
238
+ // use the default value.
239
+ $ coercedValues [$ name ] = $ argumentDefinition ->defaultValue ;
240
+ } elseif ((! $ hasValue || $ isNull ) && ($ argType instanceof NonNull)) {
241
+ // If no argument or a null value was provided to an argument with a
242
+ // non-null type (required), produce a field error.
243
+ if ($ isNull ) {
215
244
throw new Error (
216
- 'Argument " ' . $ name . '" of required type ' .
217
- '" ' . Utils::printSafe ($ argType ) . '" was not provided . ' ,
245
+ 'Argument " ' . $ name . '" of non-null type ' .
246
+ '" ' . Utils::printSafe ($ argType ) . '" must not be null . ' ,
218
247
$ referenceNode
219
248
);
220
249
}
221
- } elseif ($ argumentValueNode instanceof VariableNode) {
222
- $ variableName = $ argumentValueNode ->name ->value ;
223
250
224
- if ($ variableValues !== null && array_key_exists ($ variableName , $ variableValues )) {
225
- // Note: this does not check that this variable value is correct.
226
- // This assumes that this query has been validated and the variable
227
- // usage here is of the correct type.
228
- $ coercedValues [$ name ] = $ variableValues [$ variableName ];
229
- } elseif ($ argumentDefinition ->defaultValueExists ()) {
230
- $ coercedValues [$ name ] = $ argumentDefinition ->defaultValue ;
231
- } elseif ($ argType instanceof NonNull) {
251
+ if ($ argumentValueNode instanceof VariableNode) {
252
+ $ variableName = $ argumentValueNode ->name ->value ;
232
253
throw new Error (
233
254
'Argument " ' . $ name . '" of required type " ' . Utils::printSafe ($ argType ) . '" was ' .
234
255
'provided the variable "$ ' . $ variableName . '" which was not provided ' .
235
256
'a runtime value. ' ,
236
257
[$ argumentValueNode ]
237
258
);
238
259
}
239
- } else {
240
- $ valueNode = $ argumentValueNode ;
241
- $ coercedValue = AST ::valueFromAST ($ valueNode , $ argType , $ variableValues );
242
- if (Utils::isInvalid ($ coercedValue )) {
243
- // Note: ValuesOfCorrectType validation should catch this before
244
- // execution. This is a runtime check to ensure execution does not
245
- // continue with an invalid argument value.
246
- throw new Error (
247
- 'Argument " ' . $ name . '" has invalid value ' . Printer::doPrint ($ valueNode ) . '. ' ,
248
- [$ argumentValueNode ]
249
- );
260
+
261
+ throw new Error (
262
+ 'Argument " ' . $ name . '" of required type ' .
263
+ '" ' . Utils::printSafe ($ argType ) . '" was not provided. ' ,
264
+ $ referenceNode
265
+ );
266
+ } elseif ($ hasValue ) {
267
+ if ($ argumentValueNode instanceof NullValueNode) {
268
+ // If the explicit value `null` was provided, an entry in the coerced
269
+ // values must exist as the value `null`.
270
+ $ coercedValues [$ name ] = null ;
271
+ } elseif ($ argumentValueNode instanceof VariableNode) {
272
+ $ variableName = $ argumentValueNode ->name ->value ;
273
+ Utils::invariant ($ variableValues !== null , 'Must exist for hasValue to be true. ' );
274
+ // Note: This does no further checking that this variable is correct.
275
+ // This assumes that this query has been validated and the variable
276
+ // usage here is of the correct type.
277
+ $ coercedValues [$ name ] = $ variableValues [$ variableName ] ?? null ;
278
+ } else {
279
+ $ valueNode = $ argumentValueNode ;
280
+ $ coercedValue = AST ::valueFromAST ($ valueNode , $ argType , $ variableValues );
281
+ if (Utils::isInvalid ($ coercedValue )) {
282
+ // Note: ValuesOfCorrectType validation should catch this before
283
+ // execution. This is a runtime check to ensure execution does not
284
+ // continue with an invalid argument value.
285
+ throw new Error (
286
+ 'Argument " ' . $ name . '" has invalid value ' . Printer::doPrint ($ valueNode ) . '. ' ,
287
+ [$ argumentValueNode ]
288
+ );
289
+ }
290
+ $ coercedValues [$ name ] = $ coercedValue ;
250
291
}
251
- $ coercedValues [$ name ] = $ coercedValue ;
252
292
}
253
293
}
254
294
0 commit comments