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

DataTransferObject::mutable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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