Automattic\WooCommerce\Vendor\GraphQL\Utils

AST::astFromValuepublic staticWC 1.0

Produces a Automattic\WooCommerce\Vendor\GraphQL Value AST given a PHP value.

Optionally, a Automattic\WooCommerce\Vendor\GraphQL type may be provided, which will be used to disambiguate between value primitives.

PHP Value Automattic\WooCommerce\Vendor\GraphQL Value
Object Input Object
Assoc Array Input Object
Array List
Boolean Boolean
String String / Enum Value
Int Int
Float Int / Float
Mixed Enum Value
null NullValue

Method of the class: AST{}

No Hooks.

Returns

(ValueNode&Node)|null.

Usage

$result = AST::astFromValue( $value, $type ): ?ValueNode;
$value(mixed) (required)
.
$type(InputType&Type) (required)
.

AST::astFromValue() code WC 10.9.1

public static function astFromValue($value, InputType $type): ?ValueNode
{
    if ($type instanceof NonNull) {
        $wrappedType = $type->getWrappedType();
        assert($wrappedType instanceof InputType);

        $astValue = self::astFromValue($value, $wrappedType);

        return $astValue instanceof NullValueNode
            ? null
            : $astValue;
    }

    if ($value === null) {
        return new NullValueNode([]);
    }

    // Convert PHP iterables to Automattic\WooCommerce\Vendor\GraphQL list. If the GraphQLType is a list, but
    // the value is not an array, convert the value using the list's item type.
    if ($type instanceof ListOfType) {
        $itemType = $type->getWrappedType();
        assert($itemType instanceof InputType, 'proven by schema validation');

        if (is_iterable($value)) {
            $valuesNodes = [];
            foreach ($value as $item) {
                $itemNode = self::astFromValue($item, $itemType);
                if ($itemNode !== null) {
                    $valuesNodes[] = $itemNode;
                }
            }

            return new ListValueNode(['values' => new NodeList($valuesNodes)]);
        }

        return self::astFromValue($value, $itemType);
    }

    // Populate the fields of the input object by creating ASTs from each value
    // in the PHP object according to the fields in the input type.
    if ($type instanceof InputObjectType) {
        $isArray = is_array($value);
        $isArrayLike = $isArray || $value instanceof \ArrayAccess;
        if (! $isArrayLike && ! is_object($value)) {
            return null;
        }

        $fields = $type->getFields();
        $fieldNodes = [];
        foreach ($fields as $fieldName => $field) {
            $fieldValue = $isArrayLike
                ? $value[$fieldName] ?? null
                : $value->{$fieldName} ?? null;

            // Have to check additionally if key exists, since we differentiate between
            // "no key" and "value is null":
            if ($fieldValue !== null) {
                $fieldExists = true;
            } elseif ($isArray) {
                $fieldExists = array_key_exists($fieldName, $value);
            } elseif ($isArrayLike) {
                $fieldExists = $value->offsetExists($fieldName);
            } else {
                $fieldExists = property_exists($value, $fieldName);
            }

            if (! $fieldExists) {
                continue;
            }

            $fieldNode = self::astFromValue($fieldValue, $field->getType());

            if ($fieldNode === null) {
                continue;
            }

            $fieldNodes[] = new ObjectFieldNode([
                'name' => new NameNode(['value' => $fieldName]),
                'value' => $fieldNode,
            ]);
        }

        return new ObjectValueNode(['fields' => new NodeList($fieldNodes)]);
    }

    assert($type instanceof LeafType, 'other options were exhausted');

    // Since value is an internally represented value, it must be serialized
    // to an externally represented value before converting into an AST.
    $serialized = $type->serialize($value);

    // Others serialize based on their corresponding PHP scalar types.
    if (is_bool($serialized)) {
        return new BooleanValueNode(['value' => $serialized]);
    }

    if (is_int($serialized)) {
        return new IntValueNode(['value' => (string) $serialized]);
    }

    if (is_float($serialized)) {
        /** @phpstan-ignore equal.notAllowed (int cast with == used for performance reasons) */
        if ((int) $serialized == $serialized) {
            return new IntValueNode(['value' => (string) $serialized]);
        }

        return new FloatValueNode(['value' => (string) $serialized]);
    }

    if (is_string($serialized)) {
        // Enum types use Enum literals.
        if ($type instanceof EnumType) {
            return new EnumValueNode(['value' => $serialized]);
        }

        // ID types can use Int literals.
        $asInt = (int) $serialized;
        if ($type instanceof IDType && (string) $asInt === $serialized) {
            return new IntValueNode(['value' => $serialized]);
        }

        // Use json_encode, which uses the same string encoding as GraphQL,
        // then remove the quotes.
        return new StringValueNode(['value' => $serialized]);
    }

    $notConvertible = Utils::printSafe($serialized);
    throw new InvariantViolation("Cannot convert value to AST: {$notConvertible}");
}