Submit
Path:
~
/
/
opt
/
psa
/
admin
/
plib
/
vendor
/
webonyx
/
graphql-php
/
src
/
Validator
/
Rules
/
File Content:
PossibleFragmentSpreads.php
<?php declare(strict_types=1); namespace GraphQL\Validator\Rules; use GraphQL\Error\Error; use GraphQL\Error\InvariantViolation; use GraphQL\Language\AST\FragmentSpreadNode; use GraphQL\Language\AST\InlineFragmentNode; use GraphQL\Language\AST\NodeKind; use GraphQL\Type\Definition\AbstractType; use GraphQL\Type\Definition\CompositeType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\UnionType; use GraphQL\Type\Schema; use GraphQL\Utils\AST; use GraphQL\Validator\QueryValidationContext; class PossibleFragmentSpreads extends ValidationRule { public function getVisitor(QueryValidationContext $context): array { return [ NodeKind::INLINE_FRAGMENT => function (InlineFragmentNode $node) use ($context): void { $fragType = $context->getType(); $parentType = $context->getParentType(); if ( ! $fragType instanceof CompositeType || ! $parentType instanceof CompositeType || $this->doTypesOverlap($context->getSchema(), $fragType, $parentType) ) { return; } $context->reportError(new Error( static::typeIncompatibleAnonSpreadMessage($parentType->toString(), $fragType->toString()), [$node] )); }, NodeKind::FRAGMENT_SPREAD => function (FragmentSpreadNode $node) use ($context): void { $fragName = $node->name->value; $fragType = $this->getFragmentType($context, $fragName); $parentType = $context->getParentType(); if ( $fragType === null || $parentType === null || $this->doTypesOverlap($context->getSchema(), $fragType, $parentType) ) { return; } $context->reportError(new Error( static::typeIncompatibleSpreadMessage($fragName, $parentType->toString(), $fragType->toString()), [$node] )); }, ]; } /** * @param CompositeType&Type $fragType * @param CompositeType&Type $parentType * * @throws InvariantViolation */ protected function doTypesOverlap(Schema $schema, CompositeType $fragType, CompositeType $parentType): bool { // Checking in the order of the most frequently used scenarios: // Parent type === fragment type if ($parentType === $fragType) { return true; } // Parent type is interface or union, fragment type is object type if ($parentType instanceof AbstractType && $fragType instanceof ObjectType) { return $schema->isSubType($parentType, $fragType); } // Parent type is object type, fragment type is interface (or rather rare - union) if ($parentType instanceof ObjectType && $fragType instanceof AbstractType) { return $schema->isSubType($fragType, $parentType); } // Both are object types: if ($parentType instanceof ObjectType && $fragType instanceof ObjectType) { return $parentType === $fragType; } // Both are interfaces // This case may be assumed valid only when implementations of two interfaces intersect // But we don't have information about all implementations at runtime // (getting this information via $schema->getPossibleTypes() requires scanning through whole schema // which is very costly to do at each request due to PHP "shared nothing" architecture) // // So in this case we just make it pass - invalid fragment spreads will be simply ignored during execution // See also https://github.com/webonyx/graphql-php/issues/69#issuecomment-283954602 if ($parentType instanceof InterfaceType && $fragType instanceof InterfaceType) { return true; // Note that there is one case when we do have information about all implementations: // When schema descriptor is defined ($schema->hasDescriptor()) // BUT we must avoid situation when some query that worked in development had suddenly stopped // working in production. So staying consistent and always validate. } // Interface within union if ($parentType instanceof UnionType && $fragType instanceof InterfaceType) { foreach ($parentType->getTypes() as $type) { if ($type->implementsInterface($fragType)) { return true; } } } if ($parentType instanceof InterfaceType && $fragType instanceof UnionType) { foreach ($fragType->getTypes() as $type) { if ($type->implementsInterface($parentType)) { return true; } } } if ($parentType instanceof UnionType && $fragType instanceof UnionType) { foreach ($fragType->getTypes() as $type) { if ($parentType->isPossibleType($type)) { return true; } } } return false; } public static function typeIncompatibleAnonSpreadMessage(string $parentType, string $fragType): string { return "Fragment cannot be spread here as objects of type \"{$parentType}\" can never be of type \"{$fragType}\"."; } /** * @throws \Exception * * @return (CompositeType&Type)|null */ protected function getFragmentType(QueryValidationContext $context, string $name): ?Type { $frag = $context->getFragment($name); if ($frag === null) { return null; } $type = AST::typeFromAST([$context->getSchema(), 'getType'], $frag->typeCondition); return $type instanceof CompositeType ? $type : null; } public static function typeIncompatibleSpreadMessage(string $fragName, string $parentType, string $fragType): string { return "Fragment \"{$fragName}\" cannot be spread here as objects of type \"{$parentType}\" can never be of type \"{$fragType}\"."; } }
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
CustomValidationRule.php
982 bytes
0644
DisableIntrospection.php
1428 bytes
0644
ExecutableDefinitions.php
2093 bytes
0644
FieldsOnCorrectType.php
5239 bytes
0644
FragmentsOnCompositeTypes.php
2212 bytes
0644
KnownArgumentNames.php
2471 bytes
0644
KnownArgumentNamesOnDirectives.php
3669 bytes
0644
KnownDirectives.php
7939 bytes
0644
KnownFragmentNames.php
1023 bytes
0644
KnownTypeNames.php
3455 bytes
0644
LoneAnonymousOperation.php
1591 bytes
0644
LoneSchemaDefinition.php
1793 bytes
0644
NoFragmentCycles.php
3359 bytes
0644
NoUndefinedVariables.php
2351 bytes
0644
NoUnusedFragments.php
2229 bytes
0644
NoUnusedVariables.php
2211 bytes
0644
OverlappingFieldsCanBeMerged.php
31858 bytes
0644
PossibleFragmentSpreads.php
6390 bytes
0644
PossibleTypeExtensions.php
6340 bytes
0644
ProvidedRequiredArguments.php
2024 bytes
0644
ProvidedRequiredArgumentsOnDirectives.php
4287 bytes
0644
QueryComplexity.php
9211 bytes
0644
QueryDepth.php
4144 bytes
0644
QuerySecurityRule.php
6556 bytes
0644
ScalarLeafs.php
1687 bytes
0644
SingleFieldSubscription.php
1506 bytes
0644
UniqueArgumentDefinitionNames.php
2857 bytes
0644
UniqueArgumentNames.php
2003 bytes
0644
UniqueDirectiveNames.php
1971 bytes
0644
UniqueDirectivesPerLocation.php
3165 bytes
0644
UniqueEnumValueNames.php
2450 bytes
0644
UniqueFieldDefinitionNames.php
3831 bytes
0644
UniqueFragmentNames.php
1541 bytes
0644
UniqueInputFieldNames.php
2446 bytes
0644
UniqueOperationNames.php
1692 bytes
0644
UniqueOperationTypes.php
2420 bytes
0644
UniqueTypeNames.php
2172 bytes
0644
UniqueVariableNames.php
1473 bytes
0644
ValidationRule.php
870 bytes
0644
ValuesOfCorrectType.php
7329 bytes
0644
VariablesAreInputTypes.php
1361 bytes
0644
VariablesInAllowedPosition.php
4705 bytes
0644
N4ST4R_ID | Naxtarrr