Test Setup Failed
Push — develop ( 082d66...6f26e1 )
by Guilherme
63:04
created

ComponentMetadata::getColumnsIterator()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.5906
c 0
b 0
f 0
cc 6
eloc 12
nc 5
nop 0
1
<?php
2
3
4
declare(strict_types=1);
5
6
namespace Doctrine\ORM\Mapping;
7
8
/**
9
 * A <tt>ComponentMetadata</tt> instance holds object-relational property mapping.
10
 *
11
 * @package Doctrine\ORM\Mapping
12
 * @since 3.0
13
 *
14
 * @author Guilherme Blanco <[email protected]>
15
 */
16
abstract class ComponentMetadata
17
{
18
    /**
19
     * @var string
20
     */
21
    protected $className;
22
23
    /**
24
     * @var ComponentMetadata|null
25
     */
26
    protected $parent;
27
28
    /**
29
     * The ReflectionClass instance of the component class.
30
     *
31
     * @var \ReflectionClass|null
32
     */
33
    protected $reflectionClass;
34
35
    /**
36
     * @var CacheMetadata|null
37
     */
38
    protected $cache;
39
40
    /**
41
     * @var array<string, Property>
42
     */
43
    protected $declaredProperties = [];
44
45
    /**
46
     * ComponentMetadata constructor.
47
     *
48
     * @param string                 $className
49
     */
50
    public function __construct(string $className)
51
    {
52
        $this->className = $className;
53
    }
54
55
    /**
56
     * @return string
57
     */
58
    public function getClassName() : string
59
    {
60
        return $this->className;
61
    }
62
63
    /**
64
     * @param ComponentMetadata $parent
65
     */
66
    public function setParent(ComponentMetadata $parent) : void
67
    {
68
        $this->parent = $parent;
69
    }
70
71
    /**
72
     * @return ComponentMetadata|null
73
     */
74
    public function getParent() : ?ComponentMetadata
75
    {
76
        return $this->parent;
77
    }
78
79
    /**
80
     * @return \ReflectionClass|null
81
     */
82
    public function getReflectionClass() : ?\ReflectionClass
83
    {
84
        return $this->reflectionClass;
85
    }
86
87
    /**
88
     * @param CacheMetadata|null $cache
89
     *
90
     * @return void
91
     */
92
    public function setCache(?CacheMetadata $cache = null) : void
93
    {
94
        $this->cache = $cache;
95
    }
96
97
    /**
98
     * @return CacheMetadata|null
99
     */
100
    public function getCache(): ?CacheMetadata
101
    {
102
        return $this->cache;
103
    }
104
105
    /**
106
     * @return \ArrayIterator
107
     */
108
    public function getDeclaredPropertiesIterator() : \ArrayIterator
109
    {
110
        return new \ArrayIterator($this->declaredProperties);
111
    }
112
113
    /**
114
     * @param Property $property
115
     *
116
     * @throws MappingException
117
     */
118
    public function addDeclaredProperty(Property $property) : void
119
    {
120
        $propertyName = $property->getName();
121
122
        // @todo guilhermeblanco Switch to hasProperty once inherited properties are not being mapped on child classes
123
        if ($this->hasDeclaredProperty($propertyName)) {
124
            throw MappingException::duplicateProperty($this->getClassName(), $this->getProperty($propertyName));
0 ignored issues
show
Bug introduced by
It seems like $this->getProperty($propertyName) can be null; however, duplicateProperty() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
125
        }
126
127
        $property->setDeclaringClass($this);
128
129
        if ($this->reflectionClass) {
130
            $property->setReflectionProperty($this->reflectionClass->getProperty($propertyName));
131
        }
132
133
        $this->declaredProperties[$propertyName] = $property;
134
    }
135
136
    /**
137
     * @param string $propertyName
138
     *
139
     * @return bool
140
     */
141
    public function hasDeclaredProperty(string $propertyName) : bool
142
    {
143
        return isset($this->declaredProperties[$propertyName]);
144
    }
145
146
    /**
147
     * @return \Iterator
148
     */
149
    public function getPropertiesIterator() : \Iterator
150
    {
151
        $declaredPropertiesIterator = $this->getDeclaredPropertiesIterator();
152
153
        if (! $this->parent) {
154
            return $declaredPropertiesIterator;
155
        }
156
157
        $iterator = new \AppendIterator();
158
159
        $iterator->append($this->parent->getPropertiesIterator());
160
        $iterator->append($declaredPropertiesIterator);
161
162
        return $iterator;
163
    }
164
165
    /**
166
     * @param string $propertyName
167
     *
168
     * @return null|Property
169
     */
170
    public function getProperty(string $propertyName) : ?Property
171
    {
172
        if (isset($this->declaredProperties[$propertyName])) {
173
            return $this->declaredProperties[$propertyName];
174
        }
175
176
        if ($this->parent) {
177
            return $this->parent->getProperty($propertyName);
178
        }
179
180
        return null;
181
    }
182
183
    /**
184
     * @param string $propertyName
185
     *
186
     * @return bool
187
     */
188
    public function hasProperty(string $propertyName) : bool
189
    {
190
        if (isset($this->declaredProperties[$propertyName])) {
191
            return true;
192
        }
193
194
        return $this->parent && $this->parent->hasProperty($propertyName);
195
    }
196
197
    /**
198
     * @return \ArrayIterator
199
     */
200
    public function getColumnsIterator() : \ArrayIterator
201
    {
202
        $iterator = new \ArrayIterator();
203
204
        // @todo guilhermeblanco Must be switched to getPropertiesIterator once class only has its declared properties
205
        foreach ($this->getDeclaredPropertiesIterator() as $property) {
206
            switch (true) {
207
                case ($property instanceof FieldMetadata):
208
                    $iterator->offsetSet($property->getColumnName(), $property);
209
                    break;
210
211
                case ($property instanceof ToOneAssociationMetadata && $property->isOwningSide()):
212
                    foreach ($property->getJoinColumns() as $joinColumn) {
213
                        /** @var JoinColumnMetadata $joinColumn */
214
                        $iterator->offsetSet($joinColumn->getColumnName(), $joinColumn);
215
                    }
216
217
                    break;
218
            }
219
        }
220
221
        return $iterator;
222
    }
223
224
    /**
225
     * @param string|null $className
226
     *
227
     * @return string|null null if the input value is null
228
     */
229
    public function fullyQualifiedClassName(?string $className) : ?string
230
    {
231
        if ($className === null || ! $this->reflectionClass) {
232
            return $className;
233
        }
234
235
        $namespaceName  = $this->reflectionClass->getNamespaceName();
236
        $finalClassName = ($className !== null && strpos($className, '\\') === false && $namespaceName)
237
            ? sprintf('%s\\%s', $namespaceName, $className)
238
            : $className
239
        ;
240
241
        return ltrim($finalClassName, '\\');
242
    }
243
}
244