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
Push — master ( eaad6d...6af064 )
by Brent
11s
created

Property::shouldBeCastToCollection()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spatie\DataTransferObject;
6
7
use ReflectionProperty;
8
9
class Property extends ReflectionProperty
10
{
11
    /** @var array */
12
    protected static $typeMapping = [
13
        'int' => 'integer',
14
        'bool' => 'boolean',
15
        'float' => 'double',
16
    ];
17
18
    /** @var \Spatie\DataTransferObject\DataTransferObject */
19
    protected $valueObject;
20
21
    /** @var bool */
22
    protected $hasTypeDeclaration = false;
23
24
    /** @var bool */
25
    protected $isNullable = false;
26
27
    /** @var bool */
28
    protected $isInitialised = false;
29
30
    /** @var array */
31
    protected $types = [];
32
33
    /** @var array */
34
    protected $arrayTypes = [];
35
36
    public static function fromReflection(DataTransferObject $valueObject, ReflectionProperty $reflectionProperty)
37
    {
38
        return new self($valueObject, $reflectionProperty);
39
    }
40
41
    public function __construct(DataTransferObject $valueObject, ReflectionProperty $reflectionProperty)
42
    {
43
        parent::__construct($reflectionProperty->class, $reflectionProperty->getName());
44
45
        $this->valueObject = $valueObject;
46
47
        $this->resolveTypeDefinition();
48
    }
49
50
    public function set($value)
51
    {
52
        if (is_array($value)) {
53
            $value = $this->shouldBeCastToCollection($value) ? $this->castCollection($value) : $this->cast($value);
54
        }
55
56
        if (! $this->isValidType($value)) {
57
            throw DataTransferObjectError::invalidType($this, $value);
58
        }
59
60
        $this->isInitialised = true;
61
62
        $this->valueObject->{$this->getName()} = $value;
63
    }
64
65
    public function getTypes(): array
66
    {
67
        return $this->types;
68
    }
69
70
    public function getFqn(): string
71
    {
72
        return "{$this->getDeclaringClass()->getName()}::{$this->getName()}";
73
    }
74
75
    public function isNullable(): bool
76
    {
77
        return $this->isNullable;
78
    }
79
80
    protected function resolveTypeDefinition()
81
    {
82
        $docComment = $this->getDocComment();
83
84
        if (! $docComment) {
85
            $this->isNullable = true;
86
87
            return;
88
        }
89
90
        preg_match('/\@var ((?:(?:[\w|\\\\])+(?:\[\])?)+)/', $docComment, $matches);
91
92
        if (! count($matches)) {
93
            $this->isNullable = true;
94
95
            return;
96
        }
97
98
        $this->hasTypeDeclaration = true;
99
100
        $varDocComment = end($matches);
101
102
        $this->types = explode('|', $varDocComment);
103
        $this->arrayTypes = str_replace('[]', '', $this->types);
104
105
        $this->isNullable = strpos($varDocComment, 'null') !== false;
106
    }
107
108
    protected function isValidType($value): bool
109
    {
110
        if (! $this->hasTypeDeclaration) {
111
            return true;
112
        }
113
114
        if ($this->isNullable && $value === null) {
115
            return true;
116
        }
117
118
        foreach ($this->types as $currentType) {
119
            $isValidType = $this->assertTypeEquals($currentType, $value);
120
121
            if ($isValidType) {
122
                return true;
123
            }
124
        }
125
126
        return false;
127
    }
128
129
    protected function cast($value)
130
    {
131
        $castTo = null;
132
133
        foreach ($this->types as $type) {
134
            if (! is_subclass_of($type, DataTransferObject::class)) {
135
                continue;
136
            }
137
138
            $castTo = $type;
139
140
            break;
141
        }
142
143
        if (! $castTo) {
144
            return $value;
145
        }
146
147
        return new $castTo($value);
148
    }
149
150
    protected function castCollection(array $values)
151
    {
152
        $castTo = null;
153
154
        foreach ($this->arrayTypes as $type) {
155
            if (! is_subclass_of($type, DataTransferObject::class)) {
156
                continue;
157
            }
158
159
            $castTo = $type;
160
161
            break;
162
        }
163
164
        if (! $castTo) {
165
            return $values;
166
        }
167
168
        $casts = [];
169
170
        foreach ($values as $value) {
171
            $casts[] = new $castTo($value);
172
        }
173
174
        return $casts;
175
    }
176
177
    protected function shouldBeCastToCollection(array $values): bool
178
    {
179
        foreach ($values as $key => $value) {
180
            if (is_string($key)) {
181
                return false;
182
            }
183
184
            if (! is_array($value)) {
185
                return false;
186
            }
187
        }
188
189
        return true;
190
    }
191
192
    protected function assertTypeEquals(string $type, $value): bool
193
    {
194
        if (strpos($type, '[]') !== false) {
195
            return $this->isValidGenericCollection($type, $value);
196
        }
197
198
        if ($type === 'mixed' && $value !== null) {
199
            return true;
200
        }
201
202
        return $value instanceof $type
203
            || gettype($value) === (self::$typeMapping[$type] ?? $type);
204
    }
205
206
    protected function isValidGenericCollection(string $type, $collection): bool
207
    {
208
        if (! is_array($collection)) {
209
            return false;
210
        }
211
212
        $valueType = str_replace('[]', '', $type);
213
214
        foreach ($collection as $value) {
215
            if (! $this->assertTypeEquals($valueType, $value)) {
216
                return false;
217
            }
218
        }
219
220
        return true;
221
    }
222
}
223