Completed
Push — master ( 895aee...c5d013 )
by Arthur
8s
created

MappingGuesserManager::getBestGuess()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
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\TypeGuess;
11
use Arthem\GraphQLMapper\Mapping\SchemaContainer;
12
use Arthem\GraphQLMapper\Mapping\Type;
13
14
class MappingGuesserManager
15
{
16
    /**
17
     * @var GuesserInterface[]
18
     */
19
    private $guessers;
20
21
    /**
22
     * @param SchemaContainer $schemaContainer
23
     */
24
    public function guess(SchemaContainer $schemaContainer)
25
    {
26
        $fieldContainers = $schemaContainer->getTypes();
27
        if (null !== $query = $schemaContainer->getQuerySchema()) {
28
            $fieldContainers[] = $query;
29
        }
30
31
        foreach ($fieldContainers as $fieldContainer) {
32
            $containerContext = new ContainerContext($fieldContainer, $schemaContainer);
33
            $this->guessFields($containerContext);
34
            $this->guessTypeResolveConfig($containerContext);
35
        }
36
    }
37
38
    /**
39
     * @param ContainerContext $containerContext
40
     */
41
    private function guessFields(ContainerContext $containerContext)
42
    {
43
        foreach ($containerContext->getContainer()->getFields() as $field) {
44
            $fieldContext = $containerContext->createFieldContext($field);
45
            $this->guessFieldType($fieldContext);
46
            $this->guessFieldResolveConfig($fieldContext);
47
        }
48
    }
49
50
    /**
51
     * @param FieldContext $fieldContext
52
     */
53
    private function guessFieldType(FieldContext $fieldContext)
54
    {
55
        $field = $fieldContext->getField();
56
        if ($field->getType()) {
57
            return;
58
        }
59
60
        $guesses = [];
61 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...
62
            if ($guesser instanceof FieldTypeGuesserInterface) {
63
                $guess = $guesser->guessFieldType($fieldContext);
64
                if (null !== $guess) {
65
                    $guesses[] = $guess;
66
                }
67
            }
68
        }
69
70
        /** @var TypeGuess $best */
71
        $best = $this->getBestGuess($guesses);
72
        if (null !== $best) {
73
            $field->setType($best->getType());
74
        }
75
    }
76
77
    /**
78
     * @param ContainerContext $containerContext
79
     */
80
    private function guessTypeResolveConfig(ContainerContext $containerContext)
81
    {
82
        $guesses = [];
83
        foreach ($this->guessers as $guesser) {
84
            if ($guesser instanceof TypeResolveGuesserInterface) {
85
                $guess = $guesser->guessTypeResolveConfig($containerContext);
86
                if (null !== $guess) {
87
                    $guesses[] = $guess;
88
                }
89
            }
90
        }
91
92
        $this->applyBestGuess($containerContext->getContainer(), $guesses);
93
    }
94
95
    /**
96
     * @param FieldContext $fieldContext
97
     */
98
    private function guessFieldResolveConfig(FieldContext $fieldContext)
99
    {
100
        $guesses = [];
101 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...
102
            if ($guesser instanceof FieldResolveGuesserInterface) {
103
                $guess = $guesser->guessFieldResolveConfig($fieldContext);
104
                if (null !== $guess) {
105
                    $guesses[] = $guess;
106
                }
107
            }
108
        }
109
110
        $this->applyBestGuess($fieldContext->getField(), $guesses);
111
    }
112
113
    /**
114
     * @param AbstractType|Type|Field $item
115
     * @param array                   $guesses
116
     */
117
    private function applyBestGuess(AbstractType $item, array $guesses)
118
    {
119
        /** @var ResolveConfigGuess $best */
120
        $best = $this->getBestGuess($guesses);
121
        if (null !== $best) {
122
            $item->mergeResolveConfig($best->getConfig());
123
        }
124
    }
125
126
    /**
127
     * Return the guess most likely to be correct from a list of guesses
128
     *
129
     * @param Guess[] $guesses An array of guesses
130
     * @return Guess|null The guess with the highest confidence
131
     */
132
    public function getBestGuess(array $guesses)
133
    {
134
        $result        = null;
135
        $maxConfidence = -1;
136
137
        foreach ($guesses as $guess) {
138
            if ($maxConfidence < $confidence = $guess->getConfidence()) {
139
                $maxConfidence = $confidence;
140
                $result        = $guess;
141
            }
142
        }
143
144
        return $result;
145
    }
146
147
    /**
148
     * @param GuesserInterface $guesser
149
     * @return $this
150
     */
151
    public function addGuesser(GuesserInterface $guesser)
152
    {
153
        $this->guessers[] = $guesser;
154
155
        return $this;
156
    }
157
}
158