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 (#45)
by
unknown
01:14
created

Property   A

Complexity

Total Complexity 37

Size/Duplication

Total Lines 201
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 37
lcom 1
cbo 2
dl 0
loc 201
rs 9.44
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A fromReflection() 0 4 1
A __construct() 0 8 1
A getTypes() 0 4 1
A getFqn() 0 4 1
A isNullable() 0 4 1
A resolveTypeDefinition() 0 26 3
B isValidType() 0 20 6
A cast() 0 20 4
A set() 0 14 4
B castArray() 0 32 6
A assertTypeEquals() 0 13 5
A isValidGenericCollection() 0 16 4
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
    public static function fromReflection(DataTransferObject $valueObject, ReflectionProperty $reflectionProperty)
34
    {
35
        return new self($valueObject, $reflectionProperty);
36
    }
37
38
    public function __construct(DataTransferObject $valueObject, ReflectionProperty $reflectionProperty)
39
    {
40
        parent::__construct($reflectionProperty->class, $reflectionProperty->getName());
41
42
        $this->valueObject = $valueObject;
43
44
        $this->resolveTypeDefinition();
45
    }
46
47
    public function set($value)
48
    {
49
        if (is_array($value)) {
50
            $value = Arr::isAssoc($value) ? $this->cast($value) : $this->castArray($value);
51
        }
52
53
        if (! $this->isValidType($value)) {
54
            throw DataTransferObjectError::invalidType($this, $value);
55
        }
56
57
        $this->isInitialised = true;
58
59
        $this->valueObject->{$this->getName()} = $value;
60
    }
61
62
    public function getTypes(): array
63
    {
64
        return $this->types;
65
    }
66
67
    public function getFqn(): string
68
    {
69
        return "{$this->getDeclaringClass()->getName()}::{$this->getName()}";
70
    }
71
72
    public function isNullable(): bool
73
    {
74
        return $this->isNullable;
75
    }
76
77
    protected function resolveTypeDefinition()
78
    {
79
        $docComment = $this->getDocComment();
80
81
        if (! $docComment) {
82
            $this->isNullable = true;
83
84
            return;
85
        }
86
87
        preg_match('/\@var ((?:(?:[\w|\\\\])+(?:\[\])?)+)/', $docComment, $matches);
88
89
        if (! count($matches)) {
90
            $this->isNullable = true;
91
92
            return;
93
        }
94
95
        $this->hasTypeDeclaration = true;
96
97
        $varDocComment = end($matches);
98
99
        $this->types = explode('|', $varDocComment);
100
101
        $this->isNullable = strpos($varDocComment, 'null') !== false;
102
    }
103
104
    protected function isValidType($value): bool
105
    {
106
        if (! $this->hasTypeDeclaration) {
107
            return true;
108
        }
109
110
        if ($this->isNullable && $value === null) {
111
            return true;
112
        }
113
114
        foreach ($this->types as $currentType) {
115
            $isValidType = $this->assertTypeEquals($currentType, $value);
116
117
            if ($isValidType) {
118
                return true;
119
            }
120
        }
121
122
        return false;
123
    }
124
125
    protected function cast($value)
126
    {
127
        $castTo = null;
128
129
        foreach ($this->types as $type) {
130
            if (! is_subclass_of($type, DataTransferObject::class)) {
131
                continue;
132
            }
133
134
            $castTo = $type;
135
136
            break;
137
        }
138
139
        if (! $castTo) {
140
            return $value;
141
        }
142
143
        return new $castTo($value);
144
    }
145
146
    protected function castArray(array $values)
147
    {
148
        if (Arr::containsType($values, DataTransferObject::class)) {
149
            return $values;
150
        }
151
152
        $castTo = null;
153
        $flatTypes = str_replace('[]', '', $this->types);
154
155
        foreach ($flatTypes as $type) {
156
            if (! is_subclass_of($type, DataTransferObject::class)) {
157
                continue;
158
            }
159
160
            $castTo = $type;
161
162
            break;
163
        }
164
165
        if (! $castTo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $castTo of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
166
            return $values;
167
        }
168
169
        return array_map(
170
            function ($value) use ($castTo) {
171
                if (is_array($value)) {
172
                    return new $castTo($value);
173
                }
174
            },
175
            $values
176
        );
177
    }
178
179
    protected function assertTypeEquals(string $type, $value): bool
180
    {
181
        if (strpos($type, '[]') !== false) {
182
            return $this->isValidGenericCollection($type, $value);
183
        }
184
185
        if ($type === 'mixed' && $value !== null) {
186
            return true;
187
        }
188
189
        return $value instanceof $type
190
            || gettype($value) === (self::$typeMapping[$type] ?? $type);
191
    }
192
193
    protected function isValidGenericCollection(string $type, $collection): bool
194
    {
195
        if (! is_array($collection)) {
196
            return false;
197
        }
198
199
        $valueType = str_replace('[]', '', $type);
200
201
        foreach ($collection as $value) {
202
            if (! $this->assertTypeEquals($valueType, $value)) {
203
                return false;
204
            }
205
        }
206
207
        return true;
208
    }
209
}
210