/** * Given a type and any value, return a runtime value coerced to match the * type. * * @param TypeInterface $type * @param $value * * @return array|mixed|null|string */ protected static function coerceValue(TypeInterface $type, $value) { if ($type instanceof NonNullModifier) { // Note: we're not checking that the result of coerceValue is non-null. // We only call this function after calling isValidValue. return self::coerceValue($type->getWrappedType(), $value); } if (!isset($value)) { return NULL; } if ($type instanceof ListModifier) { $itemType = $type->getWrappedType(); if (is_array($value)) { return array_map(function ($item) use($itemType) { return Values::coerceValue($itemType, $item); }, $value); } else { return [self::coerceValue($itemType, $value)]; } } if ($type instanceof InputObjectType) { $fields = $type->getFields(); $object = []; foreach ($fields as $fieldName => $field) { $fieldValue = self::coerceValue($field->getType(), $value[$fieldName]); $object[$fieldName] = $fieldValue === NULL ? $field->getDefaultValue() : $fieldValue; } return $object; } if ($type instanceof ScalarType || $type instanceof EnumType) { $coerced = $type->coerce($value); if (NULL !== $coerced) { return $coerced; } } return NULL; }
/** * Resolves the field on the given source object. * * In particular, this figures out the object that the field returns using * the resolve function, then calls completeField to coerce scalars or * execute the sub selection set for objects. * * @param ExecutionContext $context * @param ObjectType $parent * @param $source * @param $asts * @param FieldDefinition $definition * * @return array|mixed|null|string * * @throws \Exception */ protected static function resolveFieldOrError(ExecutionContext $context, ObjectType $parent, $source, $asts, FieldDefinition $definition) { $ast = $asts[0]; $type = $definition->getType(); $resolver = $definition->getResolveCallback() ?: [__CLASS__, 'defaultResolveFn']; $data = $definition->getResolveData(); $args = Values::getArgumentValues($definition->getArguments(), $ast->get('arguments'), $context->variables); try { // @todo Change the resolver function syntax to use a value object. $result = call_user_func($resolver, $source, $args, $context->root, $ast, $type, $parent, $context->schema, $data); } catch (\Exception $error) { throw $error; } return self::completeField($context, $type, $asts, $result); }