Moved GraphQL\Language\AST\Node::fromArray to GraphQL\Utils\AST::fromArray

This commit is contained in:
Vladimir Razuvaev 2017-08-20 19:50:44 +07:00
parent bd444752f8
commit 085516bdda
4 changed files with 75 additions and 59 deletions

View File

@ -38,61 +38,6 @@ abstract class Node
*/ */
public $loc; 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 * @param array $vars
*/ */

View File

@ -1,6 +1,8 @@
<?php <?php
namespace GraphQL\Language\AST; namespace GraphQL\Language\AST;
use GraphQL\Utils\AST;
/** /**
* Class NodeList * Class NodeList
* *
@ -49,7 +51,7 @@ class NodeList implements \ArrayAccess, \IteratorAggregate, \Countable
$item = $this->nodes[$offset]; $item = $this->nodes[$offset];
if (is_array($item) && isset($item['kind'])) { if (is_array($item) && isset($item['kind'])) {
$this->nodes[$offset] = $item = Node::fromArray($item); $this->nodes[$offset] = $item = AST::fromArray($item);
} }
return $item; return $item;
@ -62,7 +64,7 @@ class NodeList implements \ArrayAccess, \IteratorAggregate, \Countable
public function offsetSet($offset, $value) public function offsetSet($offset, $value)
{ {
if (is_array($value) && isset($value['kind'])) { if (is_array($value) && isset($value['kind'])) {
$value = Node::fromArray($value); $value = AST::fromArray($value);
} }
$this->nodes[$offset] = $value; $this->nodes[$offset] = $value;
} }

View File

@ -5,14 +5,16 @@ use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\BooleanValueNode; use GraphQL\Language\AST\BooleanValueNode;
use GraphQL\Language\AST\DocumentNode; use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\AST\EnumValueNode; use GraphQL\Language\AST\EnumValueNode;
use GraphQL\Language\AST\FieldNode;
use GraphQL\Language\AST\FloatValueNode; use GraphQL\Language\AST\FloatValueNode;
use GraphQL\Language\AST\IntValueNode; use GraphQL\Language\AST\IntValueNode;
use GraphQL\Language\AST\ListTypeNode; use GraphQL\Language\AST\ListTypeNode;
use GraphQL\Language\AST\ListValueNode; use GraphQL\Language\AST\ListValueNode;
use GraphQL\Language\AST\Location;
use GraphQL\Language\AST\NamedTypeNode; use GraphQL\Language\AST\NamedTypeNode;
use GraphQL\Language\AST\NameNode; use GraphQL\Language\AST\NameNode;
use GraphQL\Language\AST\Node; use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\AST\NodeList;
use GraphQL\Language\AST\NonNullTypeNode; use GraphQL\Language\AST\NonNullTypeNode;
use GraphQL\Language\AST\NullValueNode; use GraphQL\Language\AST\NullValueNode;
use GraphQL\Language\AST\ObjectFieldNode; use GraphQL\Language\AST\ObjectFieldNode;
@ -38,6 +40,72 @@ use GraphQL\Utils\Utils;
*/ */
class AST 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. * Produces a GraphQL Value AST given a PHP value.
* *

View File

@ -5,6 +5,7 @@ use GraphQL\Language\AST\Location;
use GraphQL\Language\AST\Node; use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\NodeList; use GraphQL\Language\AST\NodeList;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
use GraphQL\Utils\AST;
class SerializationTest extends \PHPUnit_Framework_TestCase class SerializationTest extends \PHPUnit_Framework_TestCase
{ {
@ -20,7 +21,7 @@ class SerializationTest extends \PHPUnit_Framework_TestCase
{ {
$kitchenSink = file_get_contents(__DIR__ . '/kitchen-sink.graphql'); $kitchenSink = file_get_contents(__DIR__ . '/kitchen-sink.graphql');
$serializedAst = json_decode(file_get_contents(__DIR__ . '/kitchen-sink.ast'), true); $serializedAst = json_decode(file_get_contents(__DIR__ . '/kitchen-sink.ast'), true);
$actualAst = Node::fromArray($serializedAst); $actualAst = AST::fromArray($serializedAst);
$parsedAst = Parser::parse($kitchenSink); $parsedAst = Parser::parse($kitchenSink);
$this->assertNodesAreEqual($parsedAst, $actualAst); $this->assertNodesAreEqual($parsedAst, $actualAst);
} }