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