/** * @param ObjectType $object * @param InterfaceType $iface * @throws \Exception */ private function assertObjectImplementsInterface(ObjectType $object, InterfaceType $iface) { $objectFieldMap = $object->getFields(); $ifaceFieldMap = $iface->getFields(); foreach ($ifaceFieldMap as $fieldName => $ifaceField) { Utils::invariant(isset($objectFieldMap[$fieldName]), "\"{$iface}\" expects field \"{$fieldName}\" but \"{$object}\" does not provide it"); /** @var $ifaceField FieldDefinition */ /** @var $objectField FieldDefinition */ $objectField = $objectFieldMap[$fieldName]; Utils::invariant($this->isEqualType($ifaceField->getType(), $objectField->getType()), "{$iface}.{$fieldName} expects type \"{$ifaceField->getType()}\" but " . "{$object}.{$fieldName} provides type \"{$objectField->getType()}"); foreach ($ifaceField->args as $ifaceArg) { /** @var $ifaceArg FieldArgument */ /** @var $objectArg FieldArgument */ $argName = $ifaceArg->name; $objectArg = $objectField->getArg($argName); // Assert interface field arg exists on object field. Utils::invariant($objectArg, "{$iface}.{$fieldName} expects argument \"{$argName}\" but {$object}.{$fieldName} does not provide it."); // Assert interface field arg type matches object field arg type. // (invariant) Utils::invariant($this->isEqualType($ifaceArg->getType(), $objectArg->getType()), "{$iface}.{$fieldName}({$argName}:) expects type \"{$ifaceArg->getType()}\" " . "but {$object}.{$fieldName}({$argName}:) provides " . "type \"{$objectArg->getType()}\""); // Assert argument set invariance. foreach ($objectField->args as $objectArg) { $argName = $objectArg->name; $ifaceArg = $ifaceField->getArg($argName); Utils::invariant($ifaceArg, "{$iface}.{$fieldName} does not define argument \"{$argName}\" but " . "{$object}.{$fieldName} provides it."); } } } }
public function __construct(array $config) { $this->name = $config['name']; $this->description = isset($config['description']) ? $config['description'] : null; $this->_config = $config; if (isset($config['interfaces'])) { InterfaceType::addImplementationToInterfaces($this); } }
public function __construct(array $config) { Utils::invariant(!empty($config['name']), 'Every type is expected to have name'); $this->name = $config['name']; $this->description = isset($config['description']) ? $config['description'] : null; $this->resolveFieldFn = isset($config['resolveField']) ? $config['resolveField'] : null; $this->_config = $config; if (isset($config['interfaces'])) { InterfaceType::addImplementationToInterfaces($this); } }
public function __construct(array $config) { Config::validate($config, ['name' => Config::STRING | Config::REQUIRED, 'fields' => Config::arrayOf(FieldDefinition::getDefinition(), Config::KEY_AS_NAME), 'description' => Config::STRING, 'interfaces' => Config::arrayOf(Config::INTERFACE_TYPE), 'isTypeOf' => Config::CALLBACK]); $this->name = $config['name']; $this->description = isset($config['description']) ? $config['description'] : null; if (isset($config['fields'])) { $this->_fields = FieldDefinition::createMap($config['fields']); } $this->_interfaces = isset($config['interfaces']) ? $config['interfaces'] : []; $this->_isTypeOf = isset($config['isTypeOf']) ? $config['isTypeOf'] : null; if (!empty($this->_interfaces)) { InterfaceType::addImplementationToInterfaces($this, $this->_interfaces); } }
public function __construct(array $config) { Utils::invariant(!empty($config['name']), 'Every type is expected to have name'); // Note: this validation is disabled by default, because it is resource-consuming // TODO: add bin/validate script to check if schema is valid during development Config::validate($config, ['name' => Config::STRING | Config::REQUIRED, 'fields' => Config::arrayOf(FieldDefinition::getDefinition(), Config::KEY_AS_NAME), 'description' => Config::STRING, 'interfaces' => Config::arrayOf(Config::INTERFACE_TYPE), 'isTypeOf' => Config::CALLBACK, 'resolveField' => Config::CALLBACK]); $this->name = $config['name']; $this->description = isset($config['description']) ? $config['description'] : null; $this->resolveFieldFn = isset($config['resolveField']) ? $config['resolveField'] : null; $this->_isTypeOf = isset($config['isTypeOf']) ? $config['isTypeOf'] : null; $this->config = $config; if (isset($config['interfaces'])) { InterfaceType::addImplementationToInterfaces($this); } }
/** * Generate connection field. * * @param string $name * @param ObjectType $nodeType * @return array */ public function getInstance($name, ObjectType $nodeType) { $isConnection = $name instanceof Connection; $connection = new RelayConnectionType(); $instanceName = $this->instanceName($name); $connectionName = !preg_match('/Connection$/', $instanceName) ? $instanceName . 'Connection' : $instanceName; $connection->setName(studly_case($connectionName)); $pageInfoType = $this->getSchema()->typeInstance('pageInfo'); $edgeType = $this->getSchema()->edgeInstance($instanceName, $nodeType); $connection->setEdgeType($edgeType); $connection->setPageInfoType($pageInfoType); $instance = $connection->toType(); $field = new ConnectionField(['args' => $isConnection ? array_merge($name->args(), RelayConnectionType::connectionArgs()) : RelayConnectionType::connectionArgs(), 'type' => $instance, 'resolve' => $isConnection ? array($name, 'resolve') : null]); if ($connection->interfaces) { InterfaceType::addImplementationToInterfaces($instance); } return $field; }
public function type($name, $fresh = false) { if (!isset($this->types[$name])) { throw new \Exception('Type ' . $name . ' not found.'); } if (!$fresh && isset($this->typesInstances[$name])) { return $this->typesInstances[$name]; } /** @var Type $type */ $type = $this->types[$name]; $type = new $type(); $type->setManager($this); $type->toType(); $this->typesInstances[$name] = $type; //Check if the object has interfaces if ($type->interfaces) { InterfaceType::addImplementationToInterfaces($type->original); } return $type; }
public function testRejectsWhenAnImplementationIsNotAPossibleType() { // rejects when an implementation is not a possible type $interfaceType = new InterfaceType(['name' => 'InterfaceType', 'fields' => []]); $subType = new ObjectType(['name' => 'SubType', 'fields' => [], 'interfaces' => []]); $tmp = new \ReflectionObject($subType); $prop = $tmp->getProperty('_interfaces'); $prop->setAccessible(true); $prop->setValue($subType, [$interfaceType]); // Sanity check the test. $this->assertEquals([$interfaceType], $subType->getInterfaces()); $this->assertSame(false, $interfaceType->isPossibleType($subType)); // Need to make sure SubType is in the schema! We rely on // possibleTypes to be able to see it unless it's explicitly used. $schema = new Schema($interfaceType, $subType); // Another sanity check. $this->assertSame($subType, $schema->getType('SubType')); $validationResult = SchemaValidator::validate($schema, [SchemaValidator::typesInterfacesMustShowThemAsPossibleRule()]); $this->assertSame(false, $validationResult->isValid); $this->assertSame(1, count($validationResult->errors)); $this->assertSame('SubType implements interface InterfaceType, but InterfaceType does ' . 'not list it as possible!', $validationResult->errors[0]->message); /* var validationResult = validateSchema( schema, [TypesInterfacesMustShowThemAsPossible] ); expect(validationResult.isValid).to.equal(false); expect(validationResult.errors.length).to.equal(1); expect(validationResult.errors[0].message).to.equal( 'SubType implements interface InterfaceType, but InterfaceType does ' + 'not list it as possible!' ); */ }
public function type($name, $fresh = false) { if (!isset($this->types[$name])) { throw new \Exception('Type ' . $name . ' not found.'); } if (!$fresh && isset($this->typesInstances[$name])) { return $this->typesInstances[$name]; } $type = $this->types[$name]; if (!is_object($type)) { $type = app($type); } $instance = $type->toType(); $this->typesInstances[$name] = $instance; //Check if the object has interfaces if ($type->interfaces) { InterfaceType::addImplementationToInterfaces($instance); } return $instance; }
/** * @param InterfaceType $type * @return GQLDefinition\InterfaceType */ private function createInterface(InterfaceType $type) { if (null !== $type->getFields()) { $this->prepareFields($type->getFields()); } $type = new GQLDefinition\InterfaceType($type->toMapping()); return $type; }
/** * @param InterfaceType $interface * @return GQLDefinition\InterfaceType */ private function createInterface(InterfaceType $interface) { if (null !== $interface->getFields()) { $this->prepareFields($interface->getFields(), $interface); } $mapping = $interface->getChildrenClassMapping(); if (!empty($mapping)) { $resolveType = function ($object) use($mapping) { foreach ($mapping as $class => $typeName) { if ($object instanceof $class) { return $this->typeResolver->getType($typeName); } } }; $interface->setResolveType($resolveType); } $interface = new GQLDefinition\InterfaceType($interface->toMapping()); return $interface; }
/** * Generate connection field. * * @param string $name * @param Closure|null $resolve * @return array */ public function connectionField($name, $resolve = null) { $type = new RelayConnectionType(); $connectionName = !preg_match('/Connection$/', $name) ? $name . 'Connection' : $name; $type->setName(studly_case($connectionName)); $type->setEdgeType($name); $instance = $type->toType(); $this->addEdge($instance, $name); $field = ['args' => RelayConnectionType::connectionArgs(), 'type' => $instance, 'resolve' => $resolve]; if ($type->interfaces) { InterfaceType::addImplementationToInterfaces($instance); } return $field; }
public function __construct() { $config = ['name' => 'Node', 'fields' => ['id' => Types::id()], 'resolveType' => [$this, 'resolveNodeType']]; parent::__construct($config); }