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:17
created

DataTransferObject::processRemainingProperties()   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 1
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\DtoContract;
10
use Spatie\DataTransferObject\Contracts\immutable;
11
use Spatie\DataTransferObject\Contracts\PropertyContract;
12
use Spatie\DataTransferObject\Exceptions\ImmutableDtoException;
13
use Spatie\DataTransferObject\Exceptions\ImmutablePropertyDtoException;
14
use Spatie\DataTransferObject\Exceptions\PropertyNotFoundDtoException;
15
use Spatie\DataTransferObject\Exceptions\UninitialisedPropertyDtoException;
16
use Spatie\DataTransferObject\Exceptions\UnknownPropertiesDtoException;
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
     * Get all public properties from the current object through reflection.
82
     * @return Property[]
83
     * @throws \ReflectionException
84
     */
85
    protected function getPublicProperties(): array
86
    {
87
        $class = new ReflectionClass(static::class);
88
89
        $properties = [];
90
        foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $reflectionProperty) {
91
            $properties[$reflectionProperty->getName()] = Property::fromReflection($reflectionProperty);
92
        }
93
94
        return $properties;
95
    }
96
97
    /**
98
     * Check if property passes the basic conditions.
99
     * @param PropertyContract $property
100
     * @param array $parameters
101
     */
102
    protected function validateProperty(PropertyContract $property, array $parameters): void
103
    {
104
        if (!array_key_exists($property->getName(), $parameters)
105
            && is_null($property->getDefault())
106
            && !$property->nullable()
107
        ) {
108
            throw new UninitialisedPropertyDtoException($property);
109
        }
110
    }
111
112
    /**
113
     * Set the value if it's present in the array.
114
     * @param PropertyContract $property
115
     * @param array $parameters
116
     */
117
    protected function setPropertyValue(PropertyContract $property, array $parameters): void
118
    {
119
        if (array_key_exists($property->getName(), $parameters)) {
120
            $property->set($parameters[$property->getName()]);
121
        }
122
    }
123
124
    /**
125
     * Set the value if it's present in the array.
126
     * @param PropertyContract $property
127
     */
128
    protected function setPropertyDefaultValue(PropertyContract $property): void
129
    {
130
        $property->setDefault($property->getValueFromReflection($this));
131
    }
132
133
    /**
134
     * Allows to mutate the property before it gets processed.
135
     * @param PropertyContract $property
136
     * @return PropertyContract
137
     */
138
    protected function mutateProperty(PropertyContract $property): PropertyContract
139
    {
140
        return $property;
141
    }
142
143
    /**
144
     * Check if there are additional parameters left.
145
     * Throw error if there are.
146
     * Additional properties are not allowed in a dto.
147
     * @param array $parameters
148
     * @throws UnknownPropertiesDtoException
149
     */
150
    protected function processRemainingProperties(array $parameters)
151
    {
152
        if (count($parameters)) {
153
            throw new UnknownPropertiesDtoException(array_keys($parameters), static::class);
154
        }
155
    }
156
157
    /**
158
     * Immutable behavior
159
     * Throw error if a user tries to set a property.
160
     * @param $name
161
     * @param $value
162
     * @throws ImmutableDtoException|ImmutablePropertyDtoException|PropertyNotFoundDtoException
163
     */
164
    public function __set($name, $value)
165
    {
166
        if ($this->immutable) {
167
            throw new ImmutableDtoException($name);
168
        }
169
        if (!isset($this->properties[$name])) {
170
            throw new PropertyNotFoundDtoException($name, get_class($this));
171
        }
172
173
        if ($this->properties[$name]->immutable()) {
174
            throw new ImmutablePropertyDtoException($name);
175
        }
176
        $this->$name = $value;
177
    }
178
179
    /**
180
     * Proxy through to the properties array.
181
     * @param $name
182
     * @return mixed
183
     */
184
    public function __get($name)
185
    {
186
        return $this->properties[$name]->getValue();
187
    }
188
189
190
    /**
191
     * @return static
192
     */
193
    public function mutable(): DtoContract
194
    {
195
        $this->immutable = false;
196
        return $this;
197
    }
198
199
    /**
200
     * @return static
201
     */
202
    public function immutable(): DtoContract
203
    {
204
        $this->immutable = true;
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
        return $this;
235
    }
236
237
    public function toArray(): array
238
    {
239
        $data = $this->all();
240
        $array = [];
241
242
        if (count($this->onlyKeys)) {
243
            $array = array_intersect_key($data, array_flip((array)$this->onlyKeys));
244
        } else {
245
            foreach ($data as $key => $propertyValue) {
246
                if ($this->properties[$key]->isVisible())
247
                    $array[$key] = $propertyValue;
248
            }
249
        }
250
251
        return $this->parseArray($array);
252
    }
253
254
    protected function parseArray(array $array): array
255
    {
256
        foreach ($array as $key => $value) {
257
            if (
258
                $value instanceof DataTransferObject
259
                || $value instanceof DataTransferObjectCollection
260
            ) {
261
                $array[$key] = $value->toArray();
262
263
                continue;
264
            }
265
266
            if (!is_array($value)) {
267
                continue;
268
            }
269
270
            $array[$key] = $this->parseArray($value);
271
        }
272
273
        return $array;
274
    }
275
}
276