Completed
Push — master ( 52d784...7cf87e )
by Christoffer
04:08 queued 25s
created

PossibleFragmentSpreadsRule::enterNode()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 36
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 36
rs 4.909
c 0
b 0
f 0
cc 9
eloc 22
nc 9
nop 1
1
<?php
2
3
namespace Digia\GraphQL\Validation\Rule;
4
5
use Digia\GraphQL\Error\InvalidTypeException;
6
use Digia\GraphQL\Error\ValidationException;
7
use Digia\GraphQL\Language\Node\FragmentSpreadNode;
8
use Digia\GraphQL\Language\Node\InlineFragmentNode;
9
use Digia\GraphQL\Language\Node\NodeInterface;
10
use Digia\GraphQL\Type\Definition\CompositeTypeInterface;
11
use Digia\GraphQL\Type\Definition\TypeInterface;
12
use function Digia\GraphQL\Util\doTypesOverlap;
13
use function Digia\GraphQL\Util\typeFromAST;
14
use function Digia\GraphQL\Validation\typeIncompatibleAnonymousSpreadMessage;
15
use function Digia\GraphQL\Validation\typeIncompatibleSpreadMessage;
16
17
/**
18
 * Possible fragment spread
19
 *
20
 * A fragment spread is only valid if the type condition could ever possibly
21
 * be true: if there is a non-empty intersection of the possible parent types,
22
 * and possible types which pass the type condition.
23
 */
24
class PossibleFragmentSpreadsRule extends AbstractRule
25
{
26
    /**
27
     * @inheritdoc
28
     */
29
    public function enterNode(NodeInterface $node): ?NodeInterface
30
    {
31
        if ($node instanceof InlineFragmentNode) {
32
            $fragmentType = $this->validationContext->getType();
33
            $parentType   = $this->validationContext->getParentType();
34
35
            if ($fragmentType instanceof CompositeTypeInterface &&
36
                $parentType instanceof CompositeTypeInterface &&
37
                !doTypesOverlap($this->validationContext->getSchema(), $fragmentType, $parentType)) {
38
                $this->validationContext->reportError(
39
                    new ValidationException(
40
                        typeIncompatibleAnonymousSpreadMessage($parentType, $fragmentType),
0 ignored issues
show
Bug introduced by
$fragmentType of type Digia\GraphQL\Type\Defin...\CompositeTypeInterface is incompatible with the type string expected by parameter $fragmentType of Digia\GraphQL\Validation...nonymousSpreadMessage(). ( Ignorable by Annotation )

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

40
                        typeIncompatibleAnonymousSpreadMessage($parentType, /** @scrutinizer ignore-type */ $fragmentType),
Loading history...
Bug introduced by
$parentType of type Digia\GraphQL\Type\Defin...\CompositeTypeInterface is incompatible with the type string expected by parameter $parentType of Digia\GraphQL\Validation...nonymousSpreadMessage(). ( Ignorable by Annotation )

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

40
                        typeIncompatibleAnonymousSpreadMessage(/** @scrutinizer ignore-type */ $parentType, $fragmentType),
Loading history...
41
                        [$node]
42
                    )
43
                );
44
            }
45
        }
46
47
        if ($node instanceof FragmentSpreadNode) {
48
            $fragmentName = $node->getNameValue();
49
            $fragmentType = $this->getFragmentType($fragmentName);
50
            $parentType   = $this->validationContext->getParentType();
51
52
            if (null !== $fragmentType &&
53
                null !== $parentType &&
54
                !doTypesOverlap($this->validationContext->getSchema(), $fragmentType, $parentType)) {
55
                $this->validationContext->reportError(
56
                    new ValidationException(
57
                        typeIncompatibleSpreadMessage($fragmentName, $parentType, $fragmentType),
0 ignored issues
show
Bug introduced by
$parentType of type Digia\GraphQL\Type\Definition\TypeInterface is incompatible with the type string expected by parameter $parentType of Digia\GraphQL\Validation...mpatibleSpreadMessage(). ( Ignorable by Annotation )

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

57
                        typeIncompatibleSpreadMessage($fragmentName, /** @scrutinizer ignore-type */ $parentType, $fragmentType),
Loading history...
Bug introduced by
$fragmentType of type Digia\GraphQL\Type\Definition\TypeInterface is incompatible with the type string expected by parameter $fragmentType of Digia\GraphQL\Validation...mpatibleSpreadMessage(). ( Ignorable by Annotation )

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

57
                        typeIncompatibleSpreadMessage($fragmentName, $parentType, /** @scrutinizer ignore-type */ $fragmentType),
Loading history...
58
                        [$node]
59
                    )
60
                );
61
            }
62
        }
63
64
        return $node;
65
    }
66
67
    /**
68
     * @param string $name
69
     * @return TypeInterface|null
70
     * @throws InvalidTypeException
71
     */
72
    protected function getFragmentType(string $name): ?TypeInterface
73
    {
74
        $fragment = $this->validationContext->getFragment($name);
75
76
        if (null === $fragment) {
77
            return null;
78
        }
79
80
        $type = typeFromAST($this->validationContext->getSchema(), $fragment->getTypeCondition());
81
82
        return $type instanceof CompositeTypeInterface ? $type : null;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $type instanceof ...nterface ? $type : null could return the type Digia\GraphQL\Type\Defin...\CompositeTypeInterface which is incompatible with the type-hinted return null|Digia\GraphQL\Type\Definition\TypeInterface. Consider adding an additional type-check to rule them out.
Loading history...
83
    }
84
}
85