new Deps
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user