Ability to define interface fields with closure

This commit is contained in:
vladar 2016-02-27 12:29:45 +06:00
parent f548de59fe
commit d37fb34e96
2 changed files with 52 additions and 2 deletions

View File

@ -49,6 +49,10 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
}
}
/**
* InterfaceType constructor.
* @param array $config
*/
public function __construct(array $config)
{
Config::validate($config, [
@ -63,7 +67,6 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
$this->name = $config['name'];
$this->description = isset($config['description']) ? $config['description'] : null;
$this->_fields = !empty($config['fields']) ? FieldDefinition::createMap($config['fields']) : [];
$this->_resolveTypeFn = isset($config['resolveType']) ? $config['resolveType'] : null;
$this->config = $config;
}
@ -73,11 +76,25 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
*/
public function getFields()
{
if (null === $this->_fields) {
$this->_fields = [];
$fields = isset($this->config['fields']) ? $this->config['fields'] : [];
$fields = is_callable($fields) ? call_user_func($fields) : $fields;
$this->_fields = FieldDefinition::createMap($fields);
}
return $this->_fields;
}
/**
* @param $name
* @return FieldDefinition
* @throws \Exception
*/
public function getField($name)
{
if (null === $this->_fields) {
$this->getFields();
}
Utils::invariant(isset($this->_fields[$name]), 'Field "%s" is not defined for type "%s"', $name, $this->name);
return $this->_fields[$name];
}
@ -90,6 +107,10 @@ class InterfaceType extends Type implements AbstractType, OutputType, CompositeT
return $this->_implementations;
}
/**
* @param Type $type
* @return bool
*/
public function isPossibleType(Type $type)
{
$possibleTypeNames = $this->_possibleTypeNames;

View File

@ -433,6 +433,35 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
$this->assertSame($inputObject, $schema->getType('InputObject'));
$this->assertEquals(count($inputObject->getFields()), 2);
$this->assertSame($inputObject->getField('nested')->getType(), $inputObject);
$this->assertSame($inputObject->getField('value')->getType(), Type::string());
}
public function testInterfaceTypeAllowsRecursiveDefinitions()
{
$called = false;
$interface = new InterfaceType([
'name' => 'SomeInterface',
'fields' => function() use (&$interface, &$called) {
$called = true;
return [
'value' => ['type' => Type::string()],
'nested' => ['type' => $interface ]
];
}
]);
$query = new ObjectType([
'name' => 'Query',
'fields' => [
'test' => ['type' => $interface]
]
]);
$schema = new Schema($query);
$this->assertTrue($called);
$this->assertSame($interface, $schema->getType('SomeInterface'));
$this->assertEquals(count($interface->getFields()), 2);
$this->assertSame($interface->getField('nested')->getType(), $interface);
$this->assertSame($interface->getField('value')->getType(), Type::string());
}
}