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:47 queued 36s
created

DataTransferObject::__set()   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 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spatie\DataTransferObject;
6
7
use ReflectionClass;
8
use ReflectionProperty;
9
use Spatie\DataTransferObject\Contracts\immutable;
10
use Spatie\DataTransferObject\Contracts\DtoContract;
11
use Spatie\DataTransferObject\Contracts\PropertyContract;
12
use Spatie\DataTransferObject\Exceptions\ImmutableDtoException;
13
use Spatie\DataTransferObject\Exceptions\PropertyNotFoundDtoException;
14
use Spatie\DataTransferObject\Exceptions\ImmutablePropertyDtoException;
15
use Spatie\DataTransferObject\Exceptions\UnknownPropertiesDtoException;
16
use Spatie\DataTransferObject\Exceptions\UninitialisedPropertyDtoException;
17
18
/**
19
 * Class DataTransferObject.
20
 */
21
abstract class DataTransferObject implements DtoContract
22
{
23
24
    /** @var array */
25
    protected $onlyKeys = [];
26
27
    /** @var Property[] | array */
28
    protected $properties = [];
29
30
    /** @var bool */
31
    protected $immutable = false;
32
33
    public function __construct(array $parameters)
34
    {
35
        $this->boot($parameters);
36
    }
37
38
    /**
39
     * Boot the dto and process all parameters.
40
     * @param array $parameters
41
     * @throws \ReflectionException
42
     */
43
    protected function boot(array $parameters): void
44
    {
45
        $this->resolveImmutable();
46
47
        foreach ($this->getPublicProperties() as $property) {
48
49
            /*
50
             * Do not change the order of the following methods.
51
             * External packages rely on this order.
52
             */
53
54
            $this->setPropertyDefaultValue($property);
55
56
            $property = $this->mutateProperty($property);
57
58
            $this->validateProperty($property, $parameters);
59
60
            $this->setPropertyValue($property, $parameters);
61
62
            /* add the property to an associative array with the name as key */
63
            $this->properties[$property->getName()] = $property;
64
65
            /* remove the property from the value object and parameters array  */
66
            unset($parameters[$property->getName()], $this->{$property->getName()});
67
        }
68
69
        $this->processRemainingProperties($parameters);
70
    }
71
72
    protected function resolveImmutable()
73
    {
74
        if ($this instanceof immutable) {
75
            $this->immutable = true;
76
        }
77
    }
78
79
    /**
80
     * Get all public properties from the current object through reflection.
81
     * @return Property[]
82
     * @throws \ReflectionException
83
     */
84
    protected function getPublicProperties(): array
85
    {
86
        $class = new ReflectionClass(static::class);
87
88
        $properties = [];
89
        foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $reflectionProperty) {
90
            $properties[$reflectionProperty->getName()] = Property::fromReflection($reflectionProperty);
91
        }
92
93
        return $properties;
94
    }
95
96
    /**
97
     * Check if property passes the basic conditions.
98
     * @param PropertyContract $property
99
     * @param array $parameters
100
     */
101
    protected function validateProperty(PropertyContract $property, array $parameters): void
102
    {
103
        if (! array_key_exists($property->getName(), $parameters)
104
            && is_null($property->getDefault())
105
            && ! $property->nullable()
106
        ) {
107
            throw new UninitialisedPropertyDtoException($property);
108
        }
109
    }
110
111
    /**
112
     * Set the value if it's present in the array.
113
     * @param PropertyContract $property
114
     * @param array $parameters
115
     */
116
    protected function setPropertyValue(PropertyContract $property, array $parameters): void
117
    {
118
        if (array_key_exists($property->getName(), $parameters)) {
119
            $property->set($parameters[$property->getName()]);
120
        }
121
    }
122
123
    /**
124
     * Set the value if it's present in the array.
125
     * @param PropertyContract $property
126
     */
127
    protected function setPropertyDefaultValue(PropertyContract $property): void
128
    {
129
        $property->setDefault($property->getValueFromReflection($this));
130
    }
131
132
    /**
133
     * Allows to mutate the property before it gets processed.
134
     * @param PropertyContract $property
135
     * @return PropertyContract
136
     */
137
    protected function mutateProperty(PropertyContract $property): PropertyContract
138
    {
139
        return $property;
140
    }
141
142
    /**
143
     * Check if there are additional parameters left.
144
     * Throw error if there are.
145
     * Additional properties are not allowed in a dto.
146
     * @param array $parameters
147
     * @throws UnknownPropertiesDtoException
148
     */
149
    protected function processRemainingProperties(array $parameters)
150
    {
151
        if (count($parameters)) {
152
            throw new UnknownPropertiesDtoException(array_keys($parameters), static::class);
153
        }
154
    }
155
156
    /**
157
     * Immutable behavior
158
     * Throw error if a user tries to set a property.
159
     * @param $name
160
     * @param $value
161
     * @throws ImmutableDtoException|ImmutablePropertyDtoException|PropertyNotFoundDtoException
162
     */
163
    public function __set($name, $value)
164
    {
165
        if ($this->immutable) {
166
            throw new ImmutableDtoException($name);
167
        }
168
        if (! isset($this->properties[$name])) {
169
            throw new PropertyNotFoundDtoException($name, get_class($this));
170
        }
171
172
        if ($this->properties[$name]->immutable()) {
173
            throw new ImmutablePropertyDtoException($name);
174
        }
175
        $this->$name = $value;
176
    }
177
178
    /**
179
     * Proxy through to the properties array.
180
     * @param $name
181
     * @return mixed
182
     */
183
    public function __get($name)
184
    {
185
        return $this->properties[$name]->getValue();
186
    }
187
188
    /**
189
     * @return static
190
     */
191
    public function mutable(): DtoContract
192
    {
193
        $this->immutable = false;
194
195
        return $this;
196
    }
197
198
    /**
199
     * @return static
200
     */
201
    public function immutable(): DtoContract
202
    {
203
        $this->immutable = true;
204
205
        return $this;
206
    }
207
208
    public function all(): array
209
    {
210
        $data = [];
211
212
        foreach ($this->properties as $property) {
213
            $data[$property->getName()] = $property->getValue();
214
        }
215
216
        return $data;
217
    }
218
219
    public function only(string ...$keys): DtoContract
220
    {
221
        $this->onlyKeys = array_merge($this->onlyKeys, $keys);
222
223
        return $this;
224
    }
225
226
    public function except(string ...$keys): DtoContract
227
    {
228
        foreach ($keys as $key) {
229
            $property = $this->properties[$key] ?? null;
230
            if (isset($property)) {
231
                $property->setVisible(false);
232
            }
233
        }
234
235
        return $this;
236
    }
237
238
    public function toArray(): array
239
    {
240
        $data = $this->all();
241
        $array = [];
242
243
        if (count($this->onlyKeys)) {
244
            $array = array_intersect_key($data, array_flip((array) $this->onlyKeys));
245
        } else {
246
            foreach ($data as $key => $propertyValue) {
247
                if ($this->properties[$key]->isVisible()) {
248
                    $array[$key] = $propertyValue;
249
                }
250
            }
251
        }
252
253
        return $this->parseArray($array);
254
    }
255
256
    protected function parseArray(array $array): array
257
    {
258
        foreach ($array as $key => $value) {
259
            if (
260
                $value instanceof DataTransferObject
261
                || $value instanceof DataTransferObjectCollection
262
            ) {
263
                $array[$key] = $value->toArray();
264
265
                continue;
266
            }
267
268
            if (! is_array($value)) {
269
                continue;
270
            }
271
272
            $array[$key] = $this->parseArray($value);
273
        }
274
275
        return $array;
276
    }
277
}
278