@@ -67,48 +67,9 @@ public static function getVariableValues(Schema $schema, $varDefNodes, array $in
6767 /** @var InputType|Type $varType */
6868 $ varType = TypeInfo::typeFromAST ($ schema , $ varDefNode ->type );
6969
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.
11273 $ errors [] = new Error (
11374 sprintf (
11475 '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
11778 ),
11879 [$ varDefNode ->type ]
11980 );
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+ }
120136 }
121137 }
122138
@@ -208,47 +224,71 @@ public static function getArgumentValuesForMap($fieldDefinition, $argumentValueM
208224 $ argType = $ argumentDefinition ->getType ();
209225 $ argumentValueNode = $ argumentValueMap [$ name ] ?? null ;
210226
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 ) {
215244 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 . ' ,
218247 $ referenceNode
219248 );
220249 }
221- } elseif ($ argumentValueNode instanceof VariableNode) {
222- $ variableName = $ argumentValueNode ->name ->value ;
223250
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 ;
232253 throw new Error (
233254 'Argument " ' . $ name . '" of required type " ' . Utils::printSafe ($ argType ) . '" was ' .
234255 'provided the variable "$ ' . $ variableName . '" which was not provided ' .
235256 'a runtime value. ' ,
236257 [$ argumentValueNode ]
237258 );
238259 }
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 ;
250291 }
251- $ coercedValues [$ name ] = $ coercedValue ;
252292 }
253293 }
254294
0 commit comments