GraphQL\Validator\Rules\OverlappingFieldsCanBeMerged::findConflict PHP Method

findConflict() private method

private findConflict ( $parentFieldsAreMutuallyExclusive, $responseName, array $pair1, array $pair2, ValidationContext $context ) : array | null
$parentFieldsAreMutuallyExclusive
$responseName
$pair1 array
$pair2 array
$context GraphQL\Validator\ValidationContext
return array | null
    private function findConflict($parentFieldsAreMutuallyExclusive, $responseName, array $pair1, array $pair2, ValidationContext $context)
    {
        list($parentType1, $ast1, $def1) = $pair1;
        list($parentType2, $ast2, $def2) = $pair2;
        // Not a pair.
        if ($ast1 === $ast2) {
            return null;
        }
        // Memoize, do not report the same issue twice.
        // Note: Two overlapping ASTs could be encountered both when
        // `parentFieldsAreMutuallyExclusive` is true and is false, which could
        // produce different results (when `true` being a subset of `false`).
        // However we do not need to include this piece of information when
        // memoizing since this rule visits leaf fields before their parent fields,
        // ensuring that `parentFieldsAreMutuallyExclusive` is `false` the first
        // time two overlapping fields are encountered, ensuring that the full
        // set of validation rules are always checked when necessary.
        if ($this->comparedSet->has($ast1, $ast2)) {
            return null;
        }
        $this->comparedSet->add($ast1, $ast2);
        // The return type for each field.
        $type1 = isset($def1) ? $def1->getType() : null;
        $type2 = isset($def2) ? $def2->getType() : null;
        // If it is known that two fields could not possibly apply at the same
        // time, due to the parent types, then it is safe to permit them to diverge
        // in aliased field or arguments used as they will not present any ambiguity
        // by differing.
        // It is known that two parent types could never overlap if they are
        // different Object types. Interface or Union types might overlap - if not
        // in the current state of the schema, then perhaps in some future version,
        // thus may not safely diverge.
        $fieldsAreMutuallyExclusive = $parentFieldsAreMutuallyExclusive || $parentType1 !== $parentType2 && $parentType1 instanceof ObjectType && $parentType2 instanceof ObjectType;
        if (!$fieldsAreMutuallyExclusive) {
            $name1 = $ast1->name->value;
            $name2 = $ast2->name->value;
            if ($name1 !== $name2) {
                return [[$responseName, "{$name1} and {$name2} are different fields"], [$ast1], [$ast2]];
            }
            $args1 = isset($ast1->arguments) ? $ast1->arguments : [];
            $args2 = isset($ast2->arguments) ? $ast2->arguments : [];
            if (!$this->sameArguments($args1, $args2)) {
                return [[$responseName, 'they have differing arguments'], [$ast1], [$ast2]];
            }
        }
        if ($type1 && $type2 && $this->doTypesConflict($type1, $type2)) {
            return [[$responseName, "they return conflicting types {$type1} and {$type2}"], [$ast1], [$ast2]];
        }
        $subfieldMap = $this->getSubfieldMap($ast1, $type1, $ast2, $type2, $context);
        if ($subfieldMap) {
            $conflicts = $this->findConflicts($fieldsAreMutuallyExclusive, $subfieldMap, $context);
            return $this->subfieldConflicts($conflicts, $responseName, $ast1, $ast2);
        }
        return null;
    }