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 (#14)
by Brent
03:44 queued 01:16
created

DataTransferObjectProperty::fromReflection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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