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:36
created

Property::setUninitialized()   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 array */
28
    protected $types = [];
29
30
    /** @var array */
31
    protected $arrayTypes = [];
32
33
    /** @var mixed */
34
    protected $default;
35
36
    /** @var mixed */
37
    protected $value;
38
39
    /** @var ReflectionProperty */
40
    protected $reflection;
41
42
    public static function fromReflection(ReflectionProperty $reflectionProperty): self
43
    {
44
        return new static($reflectionProperty);
45
    }
46
47
    public function __construct(ReflectionProperty $reflectionProperty)
48
    {
49
        $this->reflection = $reflectionProperty;
50
51
        $this->resolveTypeDefinition();
52
    }
53
54
    public function set($value)
55
    {
56
        if (is_array($value)) {
57
            $value = $this->shouldBeCastToCollection($value) ? $this->castCollection($value) : $this->cast($value);
58
        }
59
60
        if (! $this->isValidType($value)) {
61
            throw DataTransferObjectError::invalidType($this, $value);
62
        }
63
64
        $this->isInitialised = true;
65
66
        $this->value = $value;
67
    }
68
69
    public function setUninitialized()
70
    {
71
        $this->isInitialised = false;
72
    }
73
74
    public function getTypes(): array
75
    {
76
        return $this->types;
77
    }
78
79
    public function getFqn(): string
80
    {
81
        return "{$this->reflection->getDeclaringClass()->getName()}::{$this->reflection->getName()}";
82
    }
83
84
    public function isNullable(): bool
85
    {
86
        return $this->isNullable;
87
    }
88
89
    public function setNullable(bool $bool): void
90
    {
91
        $this->isNullable = $bool;
92
    }
93
94
    protected function resolveTypeDefinition()
95
    {
96
        $docComment = $this->reflection->getDocComment();
97
98
        if (! $docComment) {
99
            $this->setNullable(true);
100
101
            return;
102
        }
103
104
        preg_match('/\@var ((?:(?:[\w|\\\\])+(?:\[\])?)+)/', $docComment, $matches);
105
106
        if (! count($matches)) {
107
            $this->setNullable(true);
108
109
            return;
110
        }
111
112
        $this->hasTypeDeclaration = true;
113
114
        $varDocComment = end($matches);
115
116
        $this->types = explode('|', $varDocComment);
117
        $this->arrayTypes = str_replace('[]', '', $this->types);
118
119
        $this->setNullable(strpos($varDocComment, 'null') !== false);
120
    }
121
122
    protected function isValidType($value): bool
123
    {
124
        if (! $this->hasTypeDeclaration) {
125
            return true;
126
        }
127
128
        if ($this->isNullable && $value === null) {
129
            return true;
130
        }
131
132
        foreach ($this->types as $currentType) {
133
            $isValidType = $this->assertTypeEquals($currentType, $value);
134
135
            if ($isValidType) {
136
                return true;
137
            }
138
        }
139
140
        return false;
141
    }
142
143
    protected function cast($value)
144
    {
145
        $castTo = null;
146
147
        foreach ($this->types as $type) {
148
            if (! is_subclass_of($type, DataTransferObject::class)) {
149
                continue;
150
            }
151
152
            $castTo = $type;
153
154
            break;
155
        }
156
157
        if (! $castTo) {
158
            return $value;
159
        }
160
161
        return new $castTo($value);
162
    }
163
164
    protected function castCollection(array $values)
165
    {
166
        $castTo = null;
167
168
        foreach ($this->arrayTypes as $type) {
169
            if (! is_subclass_of($type, DataTransferObject::class)) {
170
                continue;
171
            }
172
173
            $castTo = $type;
174
175
            break;
176
        }
177
178
        if (! $castTo) {
179
            return $values;
180
        }
181
182
        $casts = [];
183
184
        foreach ($values as $value) {
185
            $casts[] = new $castTo($value);
186
        }
187
188
        return $casts;
189
    }
190
191
    protected function shouldBeCastToCollection(array $values): bool
192
    {
193
        if (empty($values)) {
194
            return false;
195
        }
196
197
        foreach ($values as $key => $value) {
198
            if (is_string($key)) {
199
                return false;
200
            }
201
202
            if (! is_array($value)) {
203
                return false;
204
            }
205
        }
206
207
        return true;
208
    }
209
210
    protected function assertTypeEquals(string $type, $value): bool
211
    {
212
        if (strpos($type, '[]') !== false) {
213
            return $this->isValidGenericCollection($type, $value);
214
        }
215
216
        if ($type === 'mixed' && $value !== null) {
217
            return true;
218
        }
219
220
        return $value instanceof $type
221
            || gettype($value) === (self::$typeMapping[$type] ?? $type);
222
    }
223
224
    protected function isValidGenericCollection(string $type, $collection): bool
225
    {
226
        if (! is_array($collection)) {
227
            return false;
228
        }
229
230
        $valueType = str_replace('[]', '', $type);
231
232
        foreach ($collection as $value) {
233
            if (! $this->assertTypeEquals($valueType, $value)) {
234
                return false;
235
            }
236
        }
237
238
        return true;
239
    }
240
241
    public function getDefault()
242
    {
243
        return $this->default;
244
    }
245
246
    public function setDefault($default): void
247
    {
248
        $this->default = $default;
249
    }
250
251
    public function getValue()
252
    {
253
        if (! $this->isNullable && $this->value == null) {
254
            return $this->getDefault();
255
        }
256
257
        return $this->value;
258
    }
259
260
    public function getValueFromReflection($object)
261
    {
262
        return $this->reflection->getValue($object);
263
    }
264
265
    public function getName()
266
    {
267
        return $this->reflection->getName();
268
    }
269
270
    public function __call($name, $arguments)
271
    {
272
        return call_user_func_array([$this->reflection, $name], $arguments);
273
    }
274
}
275