Completed
Pull Request — master (#103)
by Christoffer
02:28
created

PossibleFragmentSpreadsRule::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
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;
0 ignored issues
show
introduced by
The function Digia\GraphQL\Util\doTypesOverlap was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
13
use Digia\GraphQL\Util\TypeComparator;
14
use function Digia\GraphQL\Util\typeFromAST;
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
     * @var TypeComparator
29
     */
30
    protected $typeComparator;
31
32
    /**
33
     * PossibleFragmentSpreadsRule constructor.
34
     */
35
    public function __construct()
36
    {
37
        $this->typeComparator = new TypeComparator();
38
    }
39
40
41
    /**
42
     * @inheritdoc
43
     */
44
    public function enterNode(NodeInterface $node): ?NodeInterface
45
    {
46
        if ($node instanceof InlineFragmentNode) {
47
            $fragmentType = $this->validationContext->getType();
48
            $parentType   = $this->validationContext->getParentType();
49
50
            if ($fragmentType instanceof CompositeTypeInterface &&
51
                $parentType instanceof CompositeTypeInterface &&
52
                !$this->typeComparator->doTypesOverlap($this->validationContext->getSchema(),
53
                    $fragmentType, $parentType)) {
54
                $this->validationContext->reportError(
55
                    new ValidationException(
56
                        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

56
                        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

56
                        typeIncompatibleAnonymousSpreadMessage($parentType, /** @scrutinizer ignore-type */ $fragmentType),
Loading history...
57
                        [$node]
58
                    )
59
                );
60
            }
61
        }
62
63
        if ($node instanceof FragmentSpreadNode) {
64
            $fragmentName = $node->getNameValue();
65
            $fragmentType = $this->getFragmentType($fragmentName);
66
            $parentType   = $this->validationContext->getParentType();
67
68
            if (null !== $fragmentType &&
69
                null !== $parentType &&
70
                !$this->typeComparator->doTypesOverlap($this->validationContext->getSchema(),
71
                    $fragmentType, $parentType)) {
72
                $this->validationContext->reportError(
73
                    new ValidationException(
74
                        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

74
                        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

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