Passed
Pull Request — master (#26)
by Aleksei
02:07
created

Entity::getPrimaryFields()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 11
nc 12
nop 0
dl 0
loc 23
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Cycle ORM Schema Builder.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\Schema\Definition;
13
14
use Cycle\Schema\Definition\Map\FieldMap;
15
use Cycle\Schema\Definition\Map\OptionMap;
16
use Cycle\Schema\Definition\Map\RelationMap;
17
use Cycle\Schema\Exception\EntityException;
18
19
/**
20
 * Contains information about specific entity definition.
21
 */
22
final class Entity
23
{
24
    /** @var OptionMap */
25
    private $options;
26
27
    /** @var string|null */
28
    private $role;
29
30
    /** @var string|null */
31
    private $class;
32
33
    /** @var string|null */
34
    private $mapper;
35
36
    /** @var string|null */
37
    private $source;
38
39
    /** @var string|null */
40
    private $constrain;
41
42
    /** @var string|null */
43
    private $repository;
44
45
    /** @var FieldMap */
46
    private $fields;
47
48
    /** @var RelationMap */
49
    private $relations;
50
51
    /** @var array */
52
    private $schema = [];
53
54
    /** @var FieldMap */
55
    private $primaryFields;
56
57
    public function __construct()
58
    {
59
        $this->options = new OptionMap();
60
        $this->fields = new FieldMap();
61
        $this->primaryFields = new FieldMap();
62
        $this->relations = new RelationMap();
63
    }
64
65
    /**
66
     * Full entity copy.
67
     */
68
    public function __clone()
69
    {
70
        $this->options = clone $this->options;
71
        $this->fields = clone $this->fields;
72
        $this->primaryFields = clone $this->primaryFields;
73
        $this->relations = clone $this->relations;
74
    }
75
76
    public function getOptions(): OptionMap
77
    {
78
        return $this->options;
79
    }
80
81
    public function setRole(string $role): self
82
    {
83
        $this->role = $role;
84
85
        return $this;
86
    }
87
88
    public function getRole(): ?string
89
    {
90
        return $this->role;
91
    }
92
93
    public function setClass(string $class): self
94
    {
95
        $this->class = $class;
96
97
        return $this;
98
    }
99
100
    public function getClass(): ?string
101
    {
102
        return $this->class;
103
    }
104
105
    public function setMapper(?string $mapper): self
106
    {
107
        $this->mapper = $mapper;
108
109
        return $this;
110
    }
111
112
    public function getMapper(): ?string
113
    {
114
        return $this->normalizeClass($this->mapper);
115
    }
116
117
    public function setSource(?string $source): self
118
    {
119
        $this->source = $source;
120
121
        return $this;
122
    }
123
124
    public function getSource(): ?string
125
    {
126
        return $this->normalizeClass($this->source);
127
    }
128
129
    public function setConstrain(?string $constrain): self
130
    {
131
        $this->constrain = $constrain;
132
133
        return $this;
134
    }
135
136
    public function getConstrain(): ?string
137
    {
138
        return $this->normalizeClass($this->constrain);
139
    }
140
141
    public function setRepository(?string $repository): self
142
    {
143
        $this->repository = $repository;
144
145
        return $this;
146
    }
147
148
    public function getRepository(): ?string
149
    {
150
        return $this->normalizeClass($this->repository);
151
    }
152
153
    public function getFields(): FieldMap
154
    {
155
        return $this->fields;
156
    }
157
158
    public function getRelations(): RelationMap
159
    {
160
        return $this->relations;
161
    }
162
163
    public function setSchema(array $schema): Entity
164
    {
165
        $this->schema = $schema;
166
167
        return $this;
168
    }
169
170
    public function getSchema(): array
171
    {
172
        return $this->schema;
173
    }
174
175
    /**
176
     * Merge entity relations and fields.
177
     */
178
    public function merge(Entity $entity): void
179
    {
180
        foreach ($entity->getRelations() as $name => $relation) {
181
            if (!$this->relations->has($name)) {
182
                $this->relations->set($name, $relation);
183
            }
184
        }
185
186
        foreach ($entity->getFields() as $name => $field) {
187
            if (!$this->fields->has($name)) {
188
                $this->fields->set($name, $field);
189
            }
190
        }
191
    }
192
193
    /**
194
     * Check if entity has primary key
195
     */
196
    public function hasPrimaryKey(): bool
197
    {
198
        if ($this->primaryFields->count() > 0) {
199
            return true;
200
        }
201
202
        foreach ($this->getFields() as $field) {
203
            if ($field->isPrimary()) {
204
                return true;
205
            }
206
        }
207
208
        return false;
209
    }
210
211
    /**
212
     * Set primary key using column list
213
     *
214
     * @param string[] $columns
215
     */
216
    public function setPrimaryColumns(array $columns): void
217
    {
218
        $this->primaryFields = new FieldMap();
219
220
        foreach ($columns as $column) {
221
            $name = $this->fields->getKeyByColumnName($column);
222
            $this->primaryFields->set($name, $this->fields->get($name));
223
        }
224
    }
225
226
    /**
227
     * Get entity primary key property names
228
     */
229
    public function getPrimaryFields(): FieldMap
230
    {
231
        $map = new FieldMap();
232
233
        foreach ($this->getFields() as $name => $field) {
234
            if ($field->isPrimary()) {
235
                $map->set($name, $field);
236
            }
237
        }
238
239
        if ($this->primaryFields->count() === 0 XOR $map->count() === 0) {
240
            return $map->count() === 0 ? $this->primaryFields : $map;
241
        }
242
243
        if (
244
            $this->primaryFields->count() !== $map->count()
245
            || array_diff($map->getColumnNames(), $this->primaryFields->getColumnNames()) !== []
246
        ) {
247
            // todo make friendly exception
248
            throw new EntityException("Ambiguous primary key definition for `{$this->getRole()}`.");
249
        }
250
251
        return $this->primaryFields;
252
    }
253
254
    private function normalizeClass(string $class = null): ?string
255
    {
256
        if ($class === null) {
257
            return null;
258
        }
259
260
        return ltrim($class, '\\');
261
    }
262
}
263