Completed
Push — master ( a15609...d2fb4d )
by Gerrit
03:30
created

NullableMapping::collectDBALColumns()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 9
cts 9
cp 1
rs 9.6
c 0
b 0
f 0
cc 3
nc 4
nop 0
crap 3
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
 *
8
 * @license GPL-3.0
9
 *
10
 * @author Gerrit Addiks <[email protected]>
11
 */
12
13
namespace Addiks\RDMBundle\Mapping;
14
15
use Addiks\RDMBundle\Mapping\MappingInterface;
16
use Addiks\RDMBundle\Hydration\HydrationContextInterface;
17
use Addiks\RDMBundle\Exception\InvalidMappingException;
18
use Doctrine\DBAL\Schema\Column;
19
use Symfony\Component\DependencyInjection\ContainerInterface;
20
21
final class NullableMapping implements MappingInterface
22
{
23
24
    /**
25
     * @var MappingInterface
26
     */
27
    private $innerMapping;
28
29
    /**
30
     * @var Column|null
31
     */
32
    private $dbalColumn;
33
34
    /**
35
     * @var string
36
     */
37
    private $origin;
38
39 16
    public function __construct(
40
        MappingInterface $innerMapping,
41
        Column $dbalColumn = null,
42
        string $origin = "undefined"
43
    ) {
44 16
        $this->innerMapping = $innerMapping;
45 16
        $this->dbalColumn = $dbalColumn;
46 16
        $this->origin = $origin;
47 16
    }
48
49 1
    public function getDBALColumn(): ?Column
50
    {
51 1
        return $this->dbalColumn;
52
    }
53
54 1
    public function getInnerMapping(): MappingInterface
55
    {
56 1
        return $this->innerMapping;
57
    }
58
59 1
    public function describeOrigin(): string
60
    {
61 1
        return $this->origin;
62
    }
63
64 3
    public function collectDBALColumns(): array
65
    {
66
        /** @var array<Column> $dbalColumns */
67 3
        $dbalColumns = array();
68
69 3
        foreach ($this->innerMapping->collectDBALColumns() as $dbalColumn) {
70
            /** @var Column $dbalColumn */
71
72 2
            $dbalColumn = clone $dbalColumn;
73 2
            $dbalColumn->setNotnull(false);
74
75 2
            $dbalColumns[] = $dbalColumn;
76
        }
77
78 3
        if ($this->dbalColumn instanceof Column) {
79 1
            $dbalColumns[] = $this->dbalColumn;
80
        }
81
82 3
        return $dbalColumns;
83
    }
84
85 9
    public function getDeterminatorColumnName(): ?string
86
    {
87
        /** @var string|null $columnName */
88 9
        $columnName = null;
89
90 9
        if ($this->dbalColumn instanceof Column) {
91 7
            $columnName = $this->dbalColumn->getName();
92
        }
93
94 9
        return $columnName;
95
    }
96
97 4
    public function resolveValue(
98
        HydrationContextInterface $context,
99
        array $dataFromAdditionalColumns
100
    ) {
101
        /** @var mixed|null $value */
102 4
        $value = null;
103
104
        /** @var string|null $columnName */
105 4
        $columnName = $this->getDeterminatorColumnName();
106
107 4
        if (empty($columnName)) {
108
            /** @var array<Column> $columns */
109 2
            $columns = $this->collectDBALColumns();
110
111 2
            if (empty($columns)) {
112 1
                throw new InvalidMappingException(sprintf(
113 1
                    "Nullable mapping needs at least one column (or subcolumn) in %s!",
114 1
                    $this->origin
115
                ));
116
            }
117
118 1
            $columnName = array_values($columns)[0]->getName();
119
        }
120
121 3
        if (array_key_exists($columnName, $dataFromAdditionalColumns)
122 3
        && $dataFromAdditionalColumns[$columnName]) {
123 2
            $value = $this->innerMapping->resolveValue(
124 2
                $context,
125 2
                $dataFromAdditionalColumns
126
            );
127
        }
128
129 3
        return $value;
130
    }
131
132 4
    public function revertValue(
133
        HydrationContextInterface $context,
134
        $valueFromEntityField
135
    ): array {
136
        /** @var array<scalar> $data */
137 4
        $data = array();
138
139
        /** @var string|null $columnName */
140 4
        $columnName = $this->getDeterminatorColumnName();
141
142 4
        if (!is_null($valueFromEntityField)) {
143 3
            $data = $this->innerMapping->revertValue(
144 3
                $context,
145 3
                $valueFromEntityField
146
            );
147
148 3
            if (!empty($columnName) && !array_key_exists($columnName, $data)) {
149 3
                $data[$columnName] = true;
150
            }
151
152 1
        } elseif (!empty($columnName)) {
153 1
            $data[$columnName] = false;
154
        }
155
156 4
        return $data;
157
    }
158
159 1
    public function assertValue(
160
        HydrationContextInterface $context,
161
        array $dataFromAdditionalColumns,
162
        $actualValue
163
    ): void {
164 1
    }
165
166 1
    public function wakeUpMapping(ContainerInterface $container): void
167
    {
168 1
        $this->innerMapping->wakeUpMapping($container);
169 1
    }
170
171
}
172