Completed
Push — master ( 77cc29...840912 )
by Gerrit
10:19
created

ChoiceMapping   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 203
Duplicated Lines 27.09 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 87.5%

Importance

Changes 0
Metric Value
wmc 25
lcom 1
cbo 4
dl 55
loc 203
ccs 70
cts 80
cp 0.875
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 10 25 3
A getChoices() 0 4 1
A describeOrigin() 0 4 1
A collectDBALColumns() 0 18 2
A getDeterminatorColumn() 0 4 1
A getDeterminatorColumnName() 0 4 1
A addChoice() 0 4 1
B resolveValue() 22 35 5
B revertValue() 0 32 3
B assertValue() 23 32 5
A wakeUpMapping() 0 8 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Copyright (C) 2018 Gerrit Addiks.
4
 * This package (including this file) was released under the terms of the GPL-3.0.
5
 * You should have received a copy of the GNU General Public License along with this program.
6
 * If not, see <http://www.gnu.org/licenses/> or send me a mail so i can send you a copy.
7
 * @license GPL-3.0
8
 * @author Gerrit Addiks <[email protected]>
9
 */
10
11
namespace Addiks\RDMBundle\Mapping;
12
13
use Addiks\RDMBundle\Mapping\ChoiceMappingInterface;
14
use Addiks\RDMBundle\Mapping\MappingInterface;
15
use Doctrine\DBAL\Schema\Column;
16
use Doctrine\DBAL\Types\Type;
17
use Doctrine\DBAL\Types\TextType;
18
use Addiks\RDMBundle\Exception\InvalidMappingException;
19
use Addiks\RDMBundle\Hydration\HydrationContextInterface;
20
use Symfony\Component\DependencyInjection\ContainerInterface;
21
22
final class ChoiceMapping implements ChoiceMappingInterface
23
{
24
25
    /**
26
     * @var Column
27
     */
28
    private $determinatorColumn;
29
30
    /**
31
     * @var array<MappingInterface>
32
     */
33
    private $choiceMappings = array();
34
35
    /**
36
     * @var string
37
     */
38
    private $originDescription;
39
40
    /**
41
     * @param string|Column $determinatorColumn
42
     */
43 15
    public function __construct(
44
        $determinatorColumn,
45
        array $choiceMappings,
46
        string $originDescription = ""
47
    ) {
48 15 View Code Duplication
        if (!$determinatorColumn instanceof Column) {
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...
49 6
            $determinatorColumn = new Column(
50 6
                (string)$determinatorColumn,
51 6
                Type::getType('string'),
52
                [
53 6
                    'notnull' => false,
54
                    'length'  => 255,
55
                ]
56
            );
57
        }
58
59 15
        $this->determinatorColumn = clone $determinatorColumn;
60 15
        $this->originDescription = $originDescription;
61
62 15
        foreach ($choiceMappings as $determinator => $choiceMapping) {
63
            /** @var MappingInterface $choiceMapping */
64
65 14
            $this->addChoice($determinator, $choiceMapping);
66
        }
67 15
    }
68
69 1
    public function getChoices(): array
70
    {
71 1
        return $this->choiceMappings;
72
    }
73
74 1
    public function describeOrigin(): string
75
    {
76 1
        return $this->originDescription;
77
    }
78
79 3
    public function collectDBALColumns(): array
80
    {
81
        /** @var array<Column> $additionalMappings */
82
        $additionalMappings = array(
83 3
            clone $this->determinatorColumn
84
        );
85
86 3
        foreach ($this->choiceMappings as $choiceMapping) {
87
            /** @var MappingInterface $choiceMapping */
88
89 2
            $additionalMappings = array_merge(
90 2
                $additionalMappings,
91 2
                $choiceMapping->collectDBALColumns()
92
            );
93
        }
94
95 3
        return $additionalMappings;
96
    }
97
98 1
    public function getDeterminatorColumn(): Column
99
    {
100 1
        return clone $this->determinatorColumn;
101
    }
102
103 1
    public function getDeterminatorColumnName(): string
104
    {
105 1
        return $this->determinatorColumn->getName();
106
    }
107
108 14
    private function addChoice(string $determinator, MappingInterface $choiceMapping): void
109
    {
110 14
        $this->choiceMappings[$determinator] = $choiceMapping;
111 14
    }
112
113 2
    public function resolveValue(
114
        HydrationContextInterface $context,
115
        array $dataFromAdditionalColumns
116
    ) {
117
        /** @var mixed $value */
118 2
        $value = null;
119
120
        /** @var string $determinatorColumn */
121 2
        $determinatorColumn = $this->determinatorColumn->getName();
122
123 2 View Code Duplication
        if (array_key_exists($determinatorColumn, $dataFromAdditionalColumns)) {
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...
124
            /** @var string|int $determinatorValue */
125 2
            $determinatorValue = $dataFromAdditionalColumns[$determinatorColumn];
126
127 2
            if (!empty($determinatorValue) && !array_key_exists($determinatorValue, $this->choiceMappings)) {
128
                throw new InvalidMappingException(sprintf(
129
                    "Invalid option-value '%s' for choice-column '%s' on entity %s!",
130
                    $determinatorValue,
131
                    $determinatorColumn,
132
                    $context->getEntityClass()
133
                ));
134
            }
135
136 2
            if (isset($this->choiceMappings[$determinatorValue])) {
137 2
                $choiceMapping = $this->choiceMappings[$determinatorValue];
138
139 2
                $value = $choiceMapping->resolveValue(
140 2
                    $context,
141 2
                    $dataFromAdditionalColumns
142
                );
143
            }
144
        }
145
146 2
        return $value;
147
    }
148
149 3
    public function revertValue(
150
        HydrationContextInterface $context,
151
        $valueFromEntityField
152
    ): array {
153
        /** @var array<scalar> $data */
154 3
        $data = array();
155
156
        /** @var string $determinatorColumn */
157 3
        $determinatorColumn = $this->determinatorColumn->getName();
158
159
        /** @var ?scalar $determinatorValue */
0 ignored issues
show
Documentation introduced by
The doc-type ?scalar could not be parsed: Unknown type name "?scalar" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
160 3
        $determinatorValue = null;
161
162 3
        foreach ($this->choiceMappings as $choiceDeterminatorValue => $choiceMapping) {
163
            /** @var MappingInterface $choiceMapping */
164
165 3
            $choiceValue = $choiceMapping->resolveValue(
166 3
                $context,
167 3
                [] # <= I'm not sure how this parameter should be handled correctly in the future,
168
                   #    but with the current supported features it *should* be irrelevant.
169
            );
170
171 3
            if ($choiceValue === $valueFromEntityField) {
172 3
                $determinatorValue = $choiceDeterminatorValue;
173 3
                break;
174
            }
175
        }
176
177 3
        $data[$determinatorColumn] = $determinatorValue;
178
179 3
        return $data;
180
    }
181
182 2
    public function assertValue(
183
        HydrationContextInterface $context,
184
        array $dataFromAdditionalColumns,
185
        $actualValue
186
    ): void {
187
        /** @var string $determinatorColumn */
188 2
        $determinatorColumn = $this->determinatorColumn->getName();
189
190 2 View Code Duplication
        if (array_key_exists($determinatorColumn, $dataFromAdditionalColumns)) {
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...
191
            /** @var string|int $determinatorValue */
192 2
            $determinatorValue = $dataFromAdditionalColumns[$determinatorColumn];
193
194 2
            if (!empty($determinatorValue) && !array_key_exists($determinatorValue, $this->choiceMappings)) {
195
                throw new InvalidMappingException(sprintf(
196
                    "Invalid option-value '%s' for choice-column '%s' on entity %s!",
197
                    $determinatorValue,
198
                    $determinatorColumn,
199
                    $context->getEntityClass()
200
                ));
201
            }
202
203 2
            if (isset($this->choiceMappings[$determinatorValue])) {
204 2
                $choiceMapping = $this->choiceMappings[$determinatorValue];
205
206 2
                $choiceMapping->assertValue(
207 2
                    $context,
208 2
                    $dataFromAdditionalColumns,
209 2
                    $actualValue
210
                );
211
            }
212
        }
213 2
    }
214
215 1
    public function wakeUpMapping(ContainerInterface $container): void
216
    {
217 1
        foreach ($this->choiceMappings as $choiceMapping) {
218
            /** @var MappingInterface $choiceMapping */
219
220 1
            $choiceMapping->wakeUpMapping($container);
221
        }
222 1
    }
223
224
}
225