Files
GermanAirlinesVA-GraphQL/vendor/nuwave/lighthouse/src/Federation/SchemaValidator.php
T
Your Name aae17f10a6 new Deps
2021-07-26 19:46:18 +02:00

92 lines
3.1 KiB
PHP

<?php
namespace Nuwave\Lighthouse\Federation;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\FieldNode;
use GraphQL\Language\AST\SelectionSetNode;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\WrappingType;
use Nuwave\Lighthouse\Events\ValidateSchema;
use Nuwave\Lighthouse\Exceptions\FederationException;
use Nuwave\Lighthouse\Federation\Directives\ExtendsDirective;
use Nuwave\Lighthouse\Federation\Directives\ExternalDirective;
use Nuwave\Lighthouse\Federation\Directives\KeyDirective;
use Nuwave\Lighthouse\Schema\AST\ASTHelper;
use Nuwave\Lighthouse\Schema\DirectiveLocator;
class SchemaValidator
{
/**
* @var \Nuwave\Lighthouse\Schema\DirectiveLocator
*/
protected $directiveLocator;
public function __construct(DirectiveLocator $directiveLocator)
{
$this->directiveLocator = $directiveLocator;
}
public function handle(ValidateSchema $validateSchema): void
{
$schema = $validateSchema->schema;
foreach ($schema->getTypeMap() as $type) {
if ($type instanceof ObjectType) {
$this->validateObjectType($type);
}
}
}
protected function validateObjectType(ObjectType $type): void
{
$ast = $type->astNode;
if ($ast !== null) {
$directives = $this->directiveLocator->associated($ast);
/** @var \Nuwave\Lighthouse\Support\Contracts\Directive $directive */
foreach ($directives as $directive) {
if ($directive instanceof KeyDirective) {
$this->validateKeySelectionSet($directive->fields(), $type);
}
}
}
}
/**
* @throws \Nuwave\Lighthouse\Exceptions\FederationException
*/
protected function validateKeySelectionSet(SelectionSetNode $selectionSet, ObjectType $type): void
{
foreach ($selectionSet->selections as $selection) {
if (! $selection instanceof FieldNode) {
throw new FederationException("Must only use field selections in the `fields` argument of @key, got: {$selection->kind}.");
}
try {
// Throws if the field is not defined
$field = $type->getField($selection->name->value);
} catch (InvariantViolation $i) {
throw new FederationException($i->getMessage(), $i->getCode(), $i);
}
if (
ASTHelper::hasDirective($type->astNode, ExtendsDirective::NAME)
&& ! ASTHelper::hasDirective($field->astNode, ExternalDirective::NAME)
) {
throw new FederationException("A @key directive on `{$type->name}` specifies the `{$field->name}` field which has no @external directive.");
}
$nestedSelection = $selection->selectionSet;
if ($nestedSelection !== null) {
$type = $field->getType();
if ($type instanceof WrappingType) {
$type = $type->getWrappedType(true);
}
$this->validateKeySelectionSet($nestedSelection, $type);
}
}
}
}