Completed
Pull Request — master (#110)
by Christoffer
02:25
created

PossibleFragmentSpreadsRule::enterNode()   D

Complexity

Conditions 9
Paths 9

Size

Total Lines 38
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 38
rs 4.909
c 0
b 0
f 0
cc 9
eloc 24
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 Digia\GraphQL\Util\TypeComparator;
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
     * @var TypeComparator
28
     */
29
    protected $typeComparator;
30
31
    /**
32
     * PossibleFragmentSpreadsRule constructor.
33
     */
34
    public function __construct()
35
    {
36
        $this->typeComparator = new TypeComparator();
37
    }
38
39
    /**
40
     * @inheritdoc
41
     */
42
    protected function enterInlineFragment(InlineFragmentNode $node): ?NodeInterface
43
    {
44
        $fragmentType = $this->context->getType();
45
        $parentType   = $this->context->getParentType();
46
47
        if ($fragmentType instanceof CompositeTypeInterface &&
48
            $parentType instanceof CompositeTypeInterface &&
49
            !$this->typeComparator->doTypesOverlap($this->context->getSchema(),
50
                $fragmentType, $parentType)) {
51
            $this->context->reportError(
52
                new ValidationException(
53
                    typeIncompatibleAnonymousSpreadMessage($parentType, $fragmentType),
0 ignored issues
show
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

53
                    typeIncompatibleAnonymousSpreadMessage(/** @scrutinizer ignore-type */ $parentType, $fragmentType),
Loading history...
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

53
                    typeIncompatibleAnonymousSpreadMessage($parentType, /** @scrutinizer ignore-type */ $fragmentType),
Loading history...
54
                    [$node]
55
                )
56
            );
57
        }
58
59
        return $node;
60
    }
61
62
    /**
63
     * @inheritdoc
64
     */
65
    protected function enterFragmentSpread(FragmentSpreadNode $node): ?NodeInterface
66
    {
67
        $fragmentName = $node->getNameValue();
68
        $fragmentType = $this->getFragmentType($fragmentName);
69
        $parentType   = $this->context->getParentType();
70
71
        if (null !== $fragmentType &&
72
            null !== $parentType &&
73
            !$this->typeComparator->doTypesOverlap($this->context->getSchema(),
74
                $fragmentType, $parentType)) {
75
            $this->context->reportError(
76
                new ValidationException(
77
                    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

77
                    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

77
                    typeIncompatibleSpreadMessage($fragmentName, $parentType, /** @scrutinizer ignore-type */ $fragmentType),
Loading history...
78
                    [$node]
79
                )
80
            );
81
        }
82
83
        return $node;
84
    }
85
86
    /**
87
     * @param string $name
88
     * @return TypeInterface|null
89
     * @throws InvalidTypeException
90
     */
91
    protected function getFragmentType(string $name): ?TypeInterface
92
    {
93
        $fragment = $this->context->getFragment($name);
94
95
        if (null === $fragment) {
96
            return null;
97
        }
98
99
        $type = typeFromAST($this->context->getSchema(), $fragment->getTypeCondition());
100
101
        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...
102
    }
103
}
104