MappingGuesserManager::getBestGuess()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
rs 9.4285
cc 3
eloc 8
nc 3
nop 1
1
<?php
2
3
namespace Arthem\GraphQLMapper\Mapping\Guesser;
4
5
use Arthem\GraphQLMapper\Mapping\AbstractType;
6
use Arthem\GraphQLMapper\Mapping\Context\ContainerContext;
7
use Arthem\GraphQLMapper\Mapping\Context\FieldContext;
8
use Arthem\GraphQLMapper\Mapping\Field;
9
use Arthem\GraphQLMapper\Mapping\Guesser\Guess\Guess;
10
use Arthem\GraphQLMapper\Mapping\Guesser\Guess\ResolveConfigGuess;
11
use Arthem\GraphQLMapper\Mapping\Guesser\Guess\TypeGuess;
12
use Arthem\GraphQLMapper\Mapping\SchemaContainer;
13
use Arthem\GraphQLMapper\Mapping\Type;
14
15
class MappingGuesserManager
16
{
17
    /**
18
     * @var GuesserInterface[]
19
     */
20
    private $guessers;
21
22
    /**
23
     * @param SchemaContainer $schemaContainer
24
     */
25
    public function guess(SchemaContainer $schemaContainer)
26
    {
27
        $fieldContainers = $schemaContainer->getTypes() + $schemaContainer->getInterfaces();
28
        if (null !== $query = $schemaContainer->getQuerySchema()) {
29
            $fieldContainers[] = $query;
30
        }
31
32
        foreach ($fieldContainers as $fieldContainer) {
33
            $containerContext = new ContainerContext($fieldContainer, $schemaContainer);
34
            $this->guessFields($containerContext);
35
            $this->guessTypeResolveConfig($containerContext);
36
        }
37
    }
38
39
    /**
40
     * @param ContainerContext $containerContext
41
     */
42
    private function guessFields(ContainerContext $containerContext)
43
    {
44
        foreach ($containerContext->getContainer()->getFields() as $field) {
45
            $fieldContext = $containerContext->createFieldContext($field);
46
            $this->guessFieldType($fieldContext);
47
            $this->guessFieldResolveConfig($fieldContext);
48
        }
49
    }
50
51
    /**
52
     * @param FieldContext $fieldContext
53
     */
54
    private function guessFieldType(FieldContext $fieldContext)
55
    {
56
        $field = $fieldContext->getField();
57
        if ($field->getType()) {
58
            return;
59
        }
60
61
        $guesses = [];
62 View Code Duplication
        foreach ($this->guessers as $guesser) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
63
            if ($guesser instanceof FieldTypeGuesserInterface) {
64
                $guess = $guesser->guessFieldType($fieldContext);
65
                if (null !== $guess) {
66
                    $guesses[] = $guess;
67
                }
68
            }
69
        }
70
71
        /** @var TypeGuess $best */
72
        $best = $this->getBestGuess($guesses);
73
        if (null !== $best) {
74
            $field->setType($best->getType());
75
        }
76
    }
77
78
    /**
79
     * @param ContainerContext $containerContext
80
     */
81
    private function guessTypeResolveConfig(ContainerContext $containerContext)
82
    {
83
        $guesses = [];
84
        foreach ($this->guessers as $guesser) {
85
            if ($guesser instanceof TypeResolveGuesserInterface) {
86
                $guess = $guesser->guessTypeResolveConfig($containerContext);
87
                if (null !== $guess) {
88
                    $guesses[] = $guess;
89
                }
90
            }
91
        }
92
93
        $this->applyBestGuess($containerContext->getContainer(), $guesses);
94
    }
95
96
    /**
97
     * @param FieldContext $fieldContext
98
     */
99
    private function guessFieldResolveConfig(FieldContext $fieldContext)
100
    {
101
        $guesses = [];
102 View Code Duplication
        foreach ($this->guessers as $guesser) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103
            if ($guesser instanceof FieldResolveGuesserInterface) {
104
                $guess = $guesser->guessFieldResolveConfig($fieldContext);
105
                if (null !== $guess) {
106
                    $guesses[] = $guess;
107
                }
108
            }
109
        }
110
111
        $this->applyBestGuess($fieldContext->getField(), $guesses);
112
    }
113
114
    /**
115
     * @param AbstractType|Type|Field $item
116
     * @param array                   $guesses
117
     */
118
    private function applyBestGuess(AbstractType $item, array $guesses)
119
    {
120
        /** @var ResolveConfigGuess $best */
121
        $best = $this->getBestGuess($guesses);
122
        if (null !== $best) {
123
            $item->mergeResolveConfig($best->getConfig());
124
        }
125
    }
126
127
    /**
128
     * Return the guess most likely to be correct from a list of guesses
129
     *
130
     * @param Guess[] $guesses An array of guesses
131
     * @return Guess|null The guess with the highest confidence
132
     */
133
    public function getBestGuess(array $guesses)
134
    {
135
        $result        = null;
136
        $maxConfidence = -1;
137
138
        foreach ($guesses as $guess) {
139
            if ($maxConfidence < $confidence = $guess->getConfidence()) {
140
                $maxConfidence = $confidence;
141
                $result        = $guess;
142
            }
143
        }
144
145
        return $result;
146
    }
147
148
    /**
149
     * @param GuesserInterface $guesser
150
     * @return $this
151
     */
152
    public function addGuesser(GuesserInterface $guesser)
153
    {
154
        $this->guessers[] = $guesser;
155
156
        return $this;
157
    }
158
}
159