diff --git a/src/Language/AST/Node.php b/src/Language/AST/Node.php index e0485af..06d89bc 100644 --- a/src/Language/AST/Node.php +++ b/src/Language/AST/Node.php @@ -38,61 +38,6 @@ abstract class Node */ public $loc; - /** - * Converts representation of AST as associative array to Node instance. - * - * For example: - * - * ```php - * Node::fromArray([ - * 'kind' => 'ListValue', - * 'values' => [ - * ['kind' => 'StringValue', 'value' => 'my str'], - * ['kind' => 'StringValue', 'value' => 'my other str'] - * ], - * 'loc' => ['start' => 21, 'end' => 25] - * ]); - * ``` - * - * Will produce instance of `ListValueNode` where `values` prop is a lazily-evaluated `NodeList` - * returning instances of `StringValueNode` on access. - * - * This is a reverse operation for $node->toArray(true) - * - * @param array $node - * @return Node - */ - public static function fromArray(array $node) - { - if (!isset($node['kind']) || !isset(NodeKind::$classMap[$node['kind']])) { - throw new InvariantViolation("Unexpected node structure: " . Utils::printSafeJson($node)); - } - - $kind = isset($node['kind']) ? $node['kind'] : null; - $class = NodeKind::$classMap[$kind]; - $instance = new $class([]); - - if (isset($node['loc'], $node['loc']['start'], $node['loc']['end'])) { - $instance->loc = Location::create($node['loc']['start'], $node['loc']['end']); - } - - - foreach ($node as $key => $value) { - if ('loc' === $key || 'kind' === $key) { - continue ; - } - if (is_array($value)) { - if (isset($value[0]) || empty($value)) { - $value = new NodeList($value); - } else { - $value = self::fromArray($value); - } - } - $instance->{$key} = $value; - } - return $instance; - } - /** * @param array $vars */ diff --git a/src/Language/AST/NodeList.php b/src/Language/AST/NodeList.php index e470ec7..b0adb81 100644 --- a/src/Language/AST/NodeList.php +++ b/src/Language/AST/NodeList.php @@ -1,6 +1,8 @@ nodes[$offset]; if (is_array($item) && isset($item['kind'])) { - $this->nodes[$offset] = $item = Node::fromArray($item); + $this->nodes[$offset] = $item = AST::fromArray($item); } return $item; @@ -62,7 +64,7 @@ class NodeList implements \ArrayAccess, \IteratorAggregate, \Countable public function offsetSet($offset, $value) { if (is_array($value) && isset($value['kind'])) { - $value = Node::fromArray($value); + $value = AST::fromArray($value); } $this->nodes[$offset] = $value; } diff --git a/src/Utils/AST.php b/src/Utils/AST.php index 7bd3f7b..9276785 100644 --- a/src/Utils/AST.php +++ b/src/Utils/AST.php @@ -5,14 +5,16 @@ use GraphQL\Error\InvariantViolation; use GraphQL\Language\AST\BooleanValueNode; use GraphQL\Language\AST\DocumentNode; use GraphQL\Language\AST\EnumValueNode; -use GraphQL\Language\AST\FieldNode; use GraphQL\Language\AST\FloatValueNode; use GraphQL\Language\AST\IntValueNode; use GraphQL\Language\AST\ListTypeNode; use GraphQL\Language\AST\ListValueNode; +use GraphQL\Language\AST\Location; use GraphQL\Language\AST\NamedTypeNode; use GraphQL\Language\AST\NameNode; use GraphQL\Language\AST\Node; +use GraphQL\Language\AST\NodeKind; +use GraphQL\Language\AST\NodeList; use GraphQL\Language\AST\NonNullTypeNode; use GraphQL\Language\AST\NullValueNode; use GraphQL\Language\AST\ObjectFieldNode; @@ -38,6 +40,72 @@ use GraphQL\Utils\Utils; */ class AST { + /** + * Convert representation of AST as an associative array to instance of GraphQL\Language\AST\Node. + * + * For example: + * + * ```php + * Node::fromArray([ + * 'kind' => 'ListValue', + * 'values' => [ + * ['kind' => 'StringValue', 'value' => 'my str'], + * ['kind' => 'StringValue', 'value' => 'my other str'] + * ], + * 'loc' => ['start' => 21, 'end' => 25] + * ]); + * ``` + * + * Will produce instance of `ListValueNode` where `values` prop is a lazily-evaluated `NodeList` + * returning instances of `StringValueNode` on access. + * + * This is a reverse operation for $node->toArray(true) + * + * @param array $node + * @return Node + */ + public static function fromArray(array $node) + { + if (!isset($node['kind']) || !isset(NodeKind::$classMap[$node['kind']])) { + throw new InvariantViolation("Unexpected node structure: " . Utils::printSafeJson($node)); + } + + $kind = isset($node['kind']) ? $node['kind'] : null; + $class = NodeKind::$classMap[$kind]; + $instance = new $class([]); + + if (isset($node['loc'], $node['loc']['start'], $node['loc']['end'])) { + $instance->loc = Location::create($node['loc']['start'], $node['loc']['end']); + } + + + foreach ($node as $key => $value) { + if ('loc' === $key || 'kind' === $key) { + continue ; + } + if (is_array($value)) { + if (isset($value[0]) || empty($value)) { + $value = new NodeList($value); + } else { + $value = self::fromArray($value); + } + } + $instance->{$key} = $value; + } + return $instance; + } + + /** + * Convert AST node to serializable array + * + * @param Node $node + * @return array + */ + public static function toArray(Node $node) + { + return $node->toArray(true); + } + /** * Produces a GraphQL Value AST given a PHP value. * diff --git a/tests/Language/SerializationTest.php b/tests/Language/SerializationTest.php index 122423b..29299f7 100644 --- a/tests/Language/SerializationTest.php +++ b/tests/Language/SerializationTest.php @@ -5,6 +5,7 @@ use GraphQL\Language\AST\Location; use GraphQL\Language\AST\Node; use GraphQL\Language\AST\NodeList; use GraphQL\Language\Parser; +use GraphQL\Utils\AST; class SerializationTest extends \PHPUnit_Framework_TestCase { @@ -20,7 +21,7 @@ class SerializationTest extends \PHPUnit_Framework_TestCase { $kitchenSink = file_get_contents(__DIR__ . '/kitchen-sink.graphql'); $serializedAst = json_decode(file_get_contents(__DIR__ . '/kitchen-sink.ast'), true); - $actualAst = Node::fromArray($serializedAst); + $actualAst = AST::fromArray($serializedAst); $parsedAst = Parser::parse($kitchenSink); $this->assertNodesAreEqual($parsedAst, $actualAst); }