Passed
Push — master ( b97c16...98e719 )
by Dawid
04:21
created

EntityMetaData   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 199
Duplicated Lines 0 %

Test Coverage

Coverage 85.71%

Importance

Changes 0
Metric Value
dl 0
loc 199
ccs 42
cts 49
cp 0.8571
rs 10
c 0
b 0
f 0
wmc 29

21 Methods

Rating   Name   Duplication   Size   Complexity  
A getSource() 0 3 1
A __construct() 0 5 1
A isStorable() 0 3 2
A getCustomHydratorClass() 0 3 1
A setSource() 0 4 1
A makeEmbed() 0 4 1
A hasIdentifier() 0 3 1
A definesCustomHydrator() 0 3 1
A addProperty() 0 5 2
A getProperty() 0 6 2
A getIdentifier() 0 7 2
A getHydratorClassName() 0 3 1
A setCustomHydratorClass() 0 6 2
A isEmbed() 0 3 1
A definesProperties() 0 3 1
A getClass() 0 3 1
A getProperties() 0 3 1
A __sleep() 0 8 1
A getFields() 0 3 1
A createInstance() 0 7 2
A __wakeup() 0 8 3
1
<?php declare(strict_types=1);
2
3
namespace Igni\Storage\Mapping\MetaData;
4
5
use Igni\Storage\Exception\MappingException;
6
use Igni\Storage\Mapping\Strategy\Id;
7
use ReflectionClass;
8
9
/**
10
 * Keeps information how entity should be mapped.
11
 *
12
 * @package Igni\Storage\Mapping\MetaData
13
 */
14
final class EntityMetaData
15
{
16
    /**
17
     * Entity class (FQCN)
18
     * @var string
19
     */
20
    private $class;
21
22
    /**
23
     * Generated hydrator class name (not FQCN)
24
     * @var string string
25
     */
26
    private $hydratorClassName;
27
28
    /**
29
     * Entity's mapped properties metadata.
30
     * @var PropertyMetaData[]
31
     */
32
    private $properties = [];
33
34
    /**
35
     * @var ReflectionClass
36
     */
37
    private $reflectionClass;
38
39
    /**
40
     * Either name of table or connection or any other namespace
41
     * where entity is stored.
42
     * @var string
43
     */
44
    private $source;
45
46
    /**
47
     * Provides information if entity is embed entity.
48
     * @var bool
49
     */
50
    private $embed = true;
51
52
    /**
53
     * Keeps user defined hydrator's class (FQCN).
54
     * @var string
55
     */
56
    private $customHydrator;
57
58
    /**
59
     * Keeps mapped properties to storage fields.
60
     * @var string[]
61
     */
62
    private $fields = [];
63
64
    /**
65
     * Contains identifier property.
66
     * @var PropertyMetaData|null
67
     */
68
    private $identifier;
69
70
    /**
71
     * @param string $class
72
     *
73
     * @throws \ReflectionException
74
     */
75 21
    public function __construct(string $class)
76
    {
77 21
        $this->class = $class;
78 21
        $this->reflectionClass = new ReflectionClass($class);
79 21
        $this->hydratorClassName = '_' . str_replace('\\', '', $class) . 'Hydrator';
80 21
    }
81
82 2
    public function makeEmbed(): void
83
    {
84 2
        $this->source = null;
85 2
        $this->embed = true;
86 2
    }
87
88 1
    public function isEmbed(): bool
89
    {
90 1
        return $this->embed;
91
    }
92
93
    public function isStorable(): bool
94
    {
95
        return $this->source !== null && $this->hasIdentifier();
96
    }
97
98 16
    public function setSource(string $source): void
99
    {
100 16
        $this->source = $source;
101 16
        $this->embed = false;
102 16
    }
103
104 11
    public function getSource(): string
105
    {
106 11
        return $this->source;
107
    }
108
109 16
    public function setCustomHydratorClass(string $className): void
110
    {
111 16
        if (!class_exists($className)) {
112
            throw new MappingException("Cannot set parent hydrator, class (${className}) does not exists.");
113
        }
114
        $this->customHydrator = $className;
115
    }
116
117
    public function definesCustomHydrator(): bool
118
    {
119 17
        return $this->customHydrator !== null;
120
    }
121
122
    public function getCustomHydratorClass(): string
123
    {
124 16
        return $this->customHydrator;
125
    }
126
127
    public function getProperty(string $name): PropertyMetaData
128
    {
129 1
        if (!isset($this->properties[$name])) {
130
            throw new MappingException("Property ${name} is undefined.");
131
        }
132 1
        return $this->properties[$name];
133
    }
134
135
    public function addProperty(PropertyMetaData $property): void
136
    {
137 19
        $this->properties[$property->getName()] = $property;
138 19
        if ($property->getType() === Id::class) {
139 16
            $this->identifier = $property;
140
        }
141 19
    }
142
143
    public function hasIdentifier(): bool
144
    {
145 7
        return $this->identifier !== null;
146
    }
147
148
    public function getIdentifier(): PropertyMetaData
149
    {
150 7
        if (!$this->hasIdentifier()) {
151
            throw new MappingException("Entity {$this->class} defines no identifier.");
152
        }
153
154 7
        return $this->identifier;
155
    }
156
157
    public function getHydratorClassName(): string
158
    {
159 17
        return $this->hydratorClassName;
160
    }
161
162
    public function definesProperties(): bool
163
    {
164 15
        return !empty($this->properties);
165
    }
166
167
    /**
168
     * @return PropertyMetaData[]
169
     */
170
    public function getProperties(): array
171
    {
172 4
        return $this->properties;
173
    }
174
175
    public function getFields(): array
176
    {
177
        return $this->fields;
178
    }
179
180
    public function getClass(): string
181
    {
182 19
        return $this->class;
183
    }
184
185
    public function createInstance(...$arguments)
186
    {
187 1
        if ($arguments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $arguments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
188
            return $this->reflectionClass->newInstanceArgs($arguments);
189
        }
190
191 1
        return $this->reflectionClass->newInstanceWithoutConstructor();
192
    }
193
194
    public function __sleep()
195
    {
196
        return [
197 1
            'class',
198
            'hydratorClassName',
199
            'properties',
200
            'source',
201
            'customHydrator',
202
        ];
203
    }
204
205
    public function __wakeup()
206
    {
207 1
        $this->reflectionClass = new ReflectionClass($this->class);
208
209 1
        foreach ($this->properties as $property) {
210 1
            $this->fields[] = $property->getFieldName();
211 1
            if ($property->getType() === Id::class) {
212 1
                $this->identifier = $property;
213
            }
214
        }
215 1
    }
216
}
217