/** * @param Field $intField * @param Field $objField * @param AbstractInterfaceType $interface * * @return bool * * @throws ConfigurationException */ protected function assertFieldsIdentical($intField, $objField, AbstractInterfaceType $interface) { $isValid = true; if ($intField->getType()->isCompositeType() !== $objField->getType()->isCompositeType()) { $isValid = false; } if ($intField->getType()->getNamedType()->getName() != $objField->getType()->getNamedType()->getName()) { $isValid = false; } if (!$isValid) { throw new ConfigurationException(sprintf('Implementation of %s is invalid for the field %s', $interface->getName(), $objField->getName())); } }
public function testAddField() { $fieldsData = ['id' => ['type' => new IntType()]]; $config = new ObjectTypeConfig(['name' => 'UserType', 'fields' => $fieldsData]); $this->assertTrue($config->hasFields()); $idField = new Field(['name' => 'id', 'type' => new IntType()]); $idField->getName(); $nameField = new Field(['name' => 'name', 'type' => new StringType()]); $this->assertEquals(['id' => $idField], $config->getFields()); $config->addField($nameField); $this->assertEquals(['id' => $idField, 'name' => $nameField], $config->getFields()); $config->removeField('id'); $this->assertEquals(['name' => $nameField], $config->getFields()); $config->addFields(['id' => $idField]); $this->assertEquals(['name' => $nameField, 'id' => $idField], $config->getFields()); $levelField = new Field(['name' => 'level', 'type' => new IntType()]); $config->addFields([$levelField]); $this->assertEquals(['name' => $nameField, 'id' => $idField, 'level' => $levelField], $config->getFields()); }
public function testInterfaceMethods() { $interface = new TestInterfaceType(); $this->assertEquals($interface->getNamedType(), $interface->getType()); $nameField = new Field(['name' => 'name', 'type' => new StringType()]); $nameField->getName(); $this->assertEquals(['name' => $nameField], $interface->getFields()); $object = new ObjectType(['name' => 'Test', 'fields' => ['name' => new StringType()], 'interfaces' => [$interface]]); $this->assertEquals([$interface], $object->getInterfaces()); $this->assertTrue($interface->isValidValue($object)); $this->assertFalse($interface->isValidValue('invalid object')); $this->assertEquals($interface->serialize($object), $object); $interfaceType = new InterfaceType(['name' => 'UserInterface', 'fields' => ['name' => new StringType()], 'resolveType' => function ($object) { return $object; }]); $this->assertEquals('UserInterface', $interfaceType->getName()); $this->assertEquals($object, $interfaceType->resolveType($object)); $this->assertTrue($interfaceType->isValidValue($object)); $this->assertFalse($interfaceType->isValidValue('invalid object')); }
/** * @param $fieldConfig * * @dataProvider invalidFieldProvider * @expectedException Youshido\GraphQL\Exception\ConfigurationException */ public function testInvalidFieldParams($fieldConfig) { $field = new Field($fieldConfig); ConfigValidator::getInstance()->assertValidConfig($field->getConfig()); }
protected function resolveList(FieldInterface $field, AstFieldInterface $ast, $parentValue) { /** @var AstQuery $ast */ $resolvedValue = $this->doResolve($field, $ast, $parentValue); $this->resolveValidator->assertValidResolvedValueForField($field, $resolvedValue); if (null === $resolvedValue) { return null; } /** @var AbstractListType $type */ $type = $field->getType()->getNullableType(); $itemType = $type->getNamedType(); $fakeAst = clone $ast; if ($fakeAst instanceof AstQuery) { $fakeAst->setArguments([]); } $fakeField = new Field(['name' => $field->getName(), 'type' => $itemType]); $result = []; foreach ($resolvedValue as $resolvedValueItem) { try { $fakeField->getConfig()->set('resolve', function () use($resolvedValueItem) { return $resolvedValueItem; }); switch ($itemType->getNullableType()->getKind()) { case TypeMap::KIND_ENUM: case TypeMap::KIND_SCALAR: $value = $this->resolveScalar($fakeField, $fakeAst, $resolvedValueItem); break; case TypeMap::KIND_OBJECT: $value = $this->resolveObject($fakeField, $fakeAst, $resolvedValueItem); break; case TypeMap::KIND_UNION: case TypeMap::KIND_INTERFACE: $value = $this->resolveComposite($fakeField, $fakeAst, $resolvedValueItem); break; default: $value = null; } } catch (\Exception $e) { $this->executionContext->addError($e); $value = null; } $result[] = $value; } return $result; }
/** * Coroutine to walk the query and schema in DFS manner (see AbstractQueryVisitor docs for more info) and yield a * tuple of (queryNode, schemaNode, childScore) * * childScore costs are accumulated via values sent into the coroutine. * * Most of the branching in this function is just to handle the different types in a query: Queries, Unions, * Fragments (anonymous and named), and Fields. The core of the function is simple: recurse until we hit the base * case of a Field and yield that back up to the visitor up in `doVisit`. * * @param Query|Field|\Youshido\GraphQL\Parser\Ast\Interfaces\FragmentInterface $queryNode * @param FieldInterface $currentLevelAST * * @return \Generator */ protected function walkQuery($queryNode, FieldInterface $currentLevelAST) { $childrenScore = 0; if (!$queryNode instanceof FieldAst) { foreach ($queryNode->getFields() as $queryField) { if ($queryField instanceof FragmentInterface) { if ($queryField instanceof FragmentReference) { $queryField = $this->executionContext->getRequest()->getFragment($queryField->getName()); } // the next 7 lines are essentially equivalent to `yield from $this->walkQuery(...)` in PHP7. // for backwards compatibility this is equivalent. // This pattern is repeated multiple times in this function, and unfortunately cannot be extracted or // made less verbose. $gen = $this->walkQuery($queryField, $currentLevelAST); $next = $gen->current(); while ($next) { $received = (yield $next); $childrenScore += (int) $received; $next = $gen->send($received); } } else { $fieldType = $currentLevelAST->getType()->getNamedType(); if ($fieldType instanceof AbstractUnionType) { foreach ($fieldType->getTypes() as $unionFieldType) { if ($fieldAst = $unionFieldType->getField($queryField->getName())) { $gen = $this->walkQuery($queryField, $fieldAst); $next = $gen->current(); while ($next) { $received = (yield $next); $childrenScore += (int) $received; $next = $gen->send($received); } } } } elseif ($fieldType instanceof AbstractObjectType && ($fieldAst = $fieldType->getField($queryField->getName()))) { $gen = $this->walkQuery($queryField, $fieldAst); $next = $gen->current(); while ($next) { $received = (yield $next); $childrenScore += (int) $received; $next = $gen->send($received); } } } } } // sanity check. don't yield fragments; they don't contribute to cost if ($queryNode instanceof Query || $queryNode instanceof FieldAst) { // BASE CASE. If we're here we're done recursing - // this node is either a field, or a query that we've finished recursing into. (yield [$queryNode, $currentLevelAST, $childrenScore]); } }
/** * @param AbstractSchema|Field $value * * @return string|null * * //todo implement value printer */ public function resolveDefaultValue($value) { $resolvedValue = $value->getConfig()->getDefaultValue(); return $resolvedValue === null ? $resolvedValue : json_encode($resolvedValue); }