Issues (167)

Validation/Rule/PossibleFragmentSpreadsRule.php (3 issues)

1
<?php
2
3
namespace Digia\GraphQL\Validation\Rule;
4
5
use Digia\GraphQL\Error\InvariantException;
6
use Digia\GraphQL\Language\Node\FragmentSpreadNode;
7
use Digia\GraphQL\Language\Node\InlineFragmentNode;
8
use Digia\GraphQL\Language\Visitor\VisitorResult;
9
use Digia\GraphQL\Type\Definition\CompositeTypeInterface;
10
use Digia\GraphQL\Type\Definition\TypeInterface;
11
use Digia\GraphQL\Util\ConversionException;
12
use Digia\GraphQL\Util\TypeASTConverter;
13
use Digia\GraphQL\Util\TypeHelper;
14
use Digia\GraphQL\Validation\ValidationException;
15
use function Digia\GraphQL\Validation\typeIncompatibleAnonymousSpreadMessage;
16
use function Digia\GraphQL\Validation\typeIncompatibleSpreadMessage;
17
18
/**
19
 * Possible fragment spread
20
 *
21
 * A fragment spread is only valid if the type condition could ever possibly
22
 * be true: if there is a non-empty intersection of the possible parent types,
23
 * and possible types which pass the type condition.
24
 */
25
class PossibleFragmentSpreadsRule extends AbstractRule
26
{
27
    /**
28
     * @inheritdoc
29
     *
30
     * @throws InvariantException
31
     */
32
    protected function enterInlineFragment(InlineFragmentNode $node): VisitorResult
33
    {
34
        $fragmentType = $this->context->getType();
35
        $parentType   = $this->context->getParentType();
36
37
        if ($fragmentType instanceof CompositeTypeInterface &&
38
            $parentType instanceof CompositeTypeInterface &&
39
            !TypeHelper::doTypesOverlap($this->context->getSchema(), $fragmentType, $parentType)
40
        ) {
41
            $this->context->reportError(
42
                new ValidationException(
43
                    typeIncompatibleAnonymousSpreadMessage((string)$parentType, (string)$fragmentType),
44
                    [$node]
45
                )
46
            );
47
        }
48
49
        return new VisitorResult($node);
50
    }
51
52
    /**
53
     * @inheritdoc
54
     *
55
     * @throws InvariantException
56
     * @throws ConversionException
57
     */
58
    protected function enterFragmentSpread(FragmentSpreadNode $node): VisitorResult
59
    {
60
        $fragmentName = $node->getNameValue();
61
        $fragmentType = $this->getFragmentType($fragmentName);
0 ignored issues
show
It seems like $fragmentName can also be of type null; however, parameter $name of Digia\GraphQL\Validation...Rule::getFragmentType() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
        $fragmentType = $this->getFragmentType(/** @scrutinizer ignore-type */ $fragmentName);
Loading history...
62
        $parentType   = $this->context->getParentType();
63
64
        if (null !== $fragmentType &&
65
            null !== $parentType &&
66
            !TypeHelper::doTypesOverlap($this->context->getSchema(), $fragmentType, $parentType)
67
        ) {
68
            $this->context->reportError(
69
                new ValidationException(
70
                    typeIncompatibleSpreadMessage($fragmentName, (string)$parentType, (string)$fragmentType),
0 ignored issues
show
It seems like $fragmentName can also be of type null; however, parameter $fragmentName of Digia\GraphQL\Validation...mpatibleSpreadMessage() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
                    typeIncompatibleSpreadMessage(/** @scrutinizer ignore-type */ $fragmentName, (string)$parentType, (string)$fragmentType),
Loading history...
71
                    [$node]
72
                )
73
            );
74
        }
75
76
        return new VisitorResult($node);
77
    }
78
79
    /**
80
     * @param string $name
81
     * @return TypeInterface|null
82
     * @throws InvariantException
83
     * @throws ConversionException
84
     */
85
    protected function getFragmentType(string $name): ?TypeInterface
86
    {
87
        $fragment = $this->context->getFragment($name);
88
89
        if (null === $fragment) {
90
            return null;
91
        }
92
93
        $type = TypeASTConverter::convert($this->context->getSchema(), $fragment->getTypeCondition());
0 ignored issues
show
It seems like $fragment->getTypeCondition() can also be of type null; however, parameter $typeNode of Digia\GraphQL\Util\TypeASTConverter::convert() does only seem to accept Digia\GraphQL\Language\Node\TypeNodeInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
        $type = TypeASTConverter::convert($this->context->getSchema(), /** @scrutinizer ignore-type */ $fragment->getTypeCondition());
Loading history...
94
95
        return $type instanceof CompositeTypeInterface ? $type : null;
96
    }
97
}
98