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
02:42 queued 01:13
created

DataTransferObject::setPropertyValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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