GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#56)
by Arthur
01:52 queued 35s
created

Property::isInitialized()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spatie\DataTransferObject;
6
7
use ReflectionProperty;
8
9
class Property
10
{
11
    /** @var array */
12
    protected static $typeMapping = [
13
        'int' => 'integer',
14
        'bool' => 'boolean',
15
        'float' => 'double',
16
    ];
17
18
    /** @var bool */
19
    protected $hasTypeDeclaration = false;
20
21
    /** @var bool */
22
    protected $isNullable = false;
23
24
    /** @var bool */
25
    protected $isInitialised = false;
26
27
    /** @var bool */
28
    protected $isImmutable = false;
29
30
    /** @var array */
31
    protected $types = [];
32
33
    /** @var array */
34
    protected $arrayTypes = [];
35
36
    /** @var mixed */
37
    protected $default;
38
39
    /** @var mixed */
40
    protected $value;
41
42
    /** @var ReflectionProperty */
43
    protected $reflection;
44
45
    public static function fromReflection(ReflectionProperty $reflectionProperty): self
46
    {
47
        return new static($reflectionProperty);
48
    }
49
50
    public function __construct(ReflectionProperty $reflectionProperty)
51
    {
52
        $this->reflection = $reflectionProperty;
53
54
        $this->resolveTypeDefinition();
55
    }
56
57
    public function set($value)
58
    {
59
        if (is_array($value)) {
60
            $value = $this->shouldBeCastToCollection($value) ? $this->castCollection($value) : $this->cast($value);
61
        }
62
63
        if (! $this->isValidType($value)) {
64
            throw DataTransferObjectError::invalidType($this, $value);
65
        }
66
67
        $this->isInitialised = true;
68
69
        $this->value = $value;
70
    }
71
72
    public function setUninitialized()
73
    {
74
        $this->isInitialised = false;
75
    }
76
77
    public function isInitialized()
78
    {
79
        return $this->isInitialised;
80
    }
81
82
    public function getTypes(): array
83
    {
84
        return $this->types;
85
    }
86
87
    public function getFqn(): string
88
    {
89
        return "{$this->reflection->getDeclaringClass()->getName()}::{$this->reflection->getName()}";
90
    }
91
92
    public function isNullable(): bool
93
    {
94
        return $this->isNullable;
95
    }
96
97
    public function setNullable(bool $bool): void
98
    {
99
        $this->isNullable = $bool;
100
    }
101
102
    public function isImmutable(): bool
103
    {
104
        return $this->isImmutable;
105
    }
106
107
    public function setIsImmutable(bool $isImmutable): void
108
    {
109
        $this->isImmutable = $isImmutable;
110
    }
111
112
    protected function resolveTypeDefinition()
113
    {
114
        $docComment = $this->reflection->getDocComment();
115
116
        if (! $docComment) {
117
            $this->setNullable(true);
118
119
            return;
120
        }
121
122
        preg_match('/\@var ((?:(?:[\w|\\\\])+(?:\[\])?)+)/', $docComment, $matches);
123
124
        if (! count($matches)) {
125
            $this->setNullable(true);
126
127
            return;
128
        }
129
130
        $varDocComment = end($matches);
131
132
        $this->types = explode('|', $varDocComment);
133
        $this->arrayTypes = str_replace('[]', '', $this->types);
134
135
        if (in_array('immutable', $this->types) || in_array('Immutable', $this->types)) {
136
            $this->setIsImmutable(true);
137
            unset($this->types['immutable'], $this->types['Immutable']);
138
139
            if (empty($this->types)) {
140
                return;
141
            }
142
        }
143
144
        $this->hasTypeDeclaration = true;
145
146
        $this->setNullable(strpos($varDocComment, 'null') !== false);
147
    }
148
149
    protected function isValidType($value): bool
150
    {
151
        if (! $this->hasTypeDeclaration) {
152
            return true;
153
        }
154
155
        if ($this->isNullable() && $value === null) {
156
            return true;
157
        }
158
159
        foreach ($this->types as $currentType) {
160
            $isValidType = $this->assertTypeEquals($currentType, $value);
161
162
            if ($isValidType) {
163
                return true;
164
            }
165
        }
166
167
        return false;
168
    }
169
170
    protected function cast($value)
171
    {
172
        $castTo = null;
173
174
        foreach ($this->types as $type) {
175
            if (! is_subclass_of($type, DataTransferObject::class)) {
176
                continue;
177
            }
178
179
            $castTo = $type;
180
181
            break;
182
        }
183
184
        if (! $castTo) {
185
            return $value;
186
        }
187
188
        return new $castTo($value);
189
    }
190
191
    protected function castCollection(array $values)
192
    {
193
        $castTo = null;
194
195
        foreach ($this->arrayTypes as $type) {
196
            if (! is_subclass_of($type, DataTransferObject::class)) {
197
                continue;
198
            }
199
200
            $castTo = $type;
201
202
            break;
203
        }
204
205
        if (! $castTo) {
206
            return $values;
207
        }
208
209
        $casts = [];
210
211
        foreach ($values as $value) {
212
            $casts[] = new $castTo($value);
213
        }
214
215
        return $casts;
216
    }
217
218
    protected function shouldBeCastToCollection(array $values): bool
219
    {
220
        if (empty($values)) {
221
            return false;
222
        }
223
224
        foreach ($values as $key => $value) {
225
            if (is_string($key)) {
226
                return false;
227
            }
228
229
            if (! is_array($value)) {
230
                return false;
231
            }
232
        }
233
234
        return true;
235
    }
236
237
    protected function assertTypeEquals(string $type, $value): bool
238
    {
239
        if (strpos($type, '[]') !== false) {
240
            return $this->isValidGenericCollection($type, $value);
241
        }
242
243
        if ($type === 'mixed' && $value !== null) {
244
            return true;
245
        }
246
247
        return $value instanceof $type
248
            || gettype($value) === (self::$typeMapping[$type] ?? $type);
249
    }
250
251
    protected function isValidGenericCollection(string $type, $collection): bool
252
    {
253
        if (! is_array($collection)) {
254
            return false;
255
        }
256
257
        $valueType = str_replace('[]', '', $type);
258
259
        foreach ($collection as $value) {
260
            if (! $this->assertTypeEquals($valueType, $value)) {
261
                return false;
262
            }
263
        }
264
265
        return true;
266
    }
267
268
    public function getDefault()
269
    {
270
        return $this->default;
271
    }
272
273
    public function setDefault($default): void
274
    {
275
        $this->default = $default;
276
    }
277
278
    public function getValue()
279
    {
280
        if (! $this->isNullable() && $this->value == null) {
281
            return $this->getDefault();
282
        }
283
284
        return $this->value;
285
    }
286
287
    public function getValueFromReflection($object)
288
    {
289
        return $this->reflection->getValue($object);
290
    }
291
292
    public function getName()
293
    {
294
        return $this->reflection->getName();
295
    }
296
297
    public function getReflection(): ReflectionProperty
298
    {
299
        return $this->reflection;
300
    }
301
}
302