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
03:40 queued 01:33
created

DataTransferObject::toArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 0
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): self
28
    {
29
        return new static($parameters, false);
30
    }
31
32
    public static function immutable(array $parameters): self
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
87
        $properties = [];
88
        foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $reflectionProperty) {
89
            $properties[$reflectionProperty->getName()] = Property::fromReflection($reflectionProperty);
90
        }
91
92
        return $properties;
93
    }
94
95
    /**
96
     * Check if property passes the basic conditions.
97
     * @param Property $property
98
     * @param array $parameters
99
     */
100
    protected function validateProperty($property, array $parameters): void
101
    {
102
        if (! array_key_exists($property->getName(), $parameters)
103
            && is_null($property->getDefault())
104
            && ! $property->isNullable()
105
        ) {
106
            throw DataTransferObjectError::uninitialized($property);
107
        }
108
    }
109
110
    /**
111
     * Set the value if it's present in the array.
112
     * @param Property $property
113
     * @param array $parameters
114
     */
115
    protected function setPropertyValue($property, array $parameters): void
116
    {
117
        if (array_key_exists($property->getName(), $parameters)) {
118
            $property->set($parameters[$property->getName()]);
119
        }
120
    }
121
122
    /**
123
     * Set the value if it's present in the array.
124
     * @param Property $property
125
     */
126
    protected function setPropertyDefaultValue($property): void
127
    {
128
        $property->setDefault($property->getValueFromReflection($this));
129
    }
130
131
    /**
132
     * Allows to mutate the property before it gets processed.
133
     * @param Property $property
134
     * @return Property
135
     */
136
    protected function mutateProperty($property)
137
    {
138
        return $property;
139
    }
140
141
    /**
142
     * Check if there are additional parameters left.
143
     * Throw error if there are.
144
     * Additional properties are not allowed in a dto.
145
     * @param array $parameters
146
     * @throws DataTransferObjectError
147
     */
148
    protected function processRemainingProperties(array $parameters)
149
    {
150
        if (count($parameters)) {
151
            throw DataTransferObjectError::unknownProperties(array_keys($parameters), static::class);
152
        }
153
    }
154
155
    /**
156
     * Immutable behavior
157
     * Throw error if a user tries to set a property.
158
     * @param $name
159
     * @param $value
160
     * @Throws DataTransferObjectError
161
     */
162
    public function __set($name, $value)
163
    {
164
        if ($this->immutable) {
165
            throw DataTransferObjectError::immutable($name);
166
        }
167
        if (! isset($this->properties[$name])) {
168
            throw DataTransferObjectError::propertyNotFound($name, get_class($this));
169
        }
170
171
        if ($this->properties[$name]->isImmutable()) {
172
            throw DataTransferObjectError::immutableProperty($name);
173
        }
174
        $this->$name = $value;
175
    }
176
177
    /**
178
     * Proxy through to the properties array.
179
     * @param $name
180
     * @return mixed
181
     */
182
    public function __get($name)
183
    {
184
        return $this->properties[$name]->getValue();
185
    }
186
187
    public function all(): array
188
    {
189
        $data = [];
190
191
        foreach ($this->properties as $property) {
192
            $data[$property->getName()] = $property->getValue();
193
        }
194
195
        return $data;
196
    }
197
198
    public function only(string ...$keys): DtoContract
199
    {
200
        $this->onlyKeys = array_merge($this->onlyKeys, $keys);
201
202
        return $this;
203
    }
204
205
    public function except(string ...$keys): DtoContract
206
    {
207
        $this->exceptKeys = array_merge($this->exceptKeys, $keys);
208
209
        return $this;
210
    }
211
212
    public function toArray(): array
213
    {
214
        if (count($this->onlyKeys)) {
215
            $array = Arr::only($this->all(), $this->onlyKeys);
216
        } else {
217
            $array = Arr::except($this->all(), $this->exceptKeys);
218
        }
219
220
        return $this->parseArray($array);
221
    }
222
223
    protected function parseArray(array $array): array
224
    {
225
        foreach ($array as $key => $value) {
226
            if (
227
                $value instanceof DataTransferObject
228
                || $value instanceof DataTransferObjectCollection
229
            ) {
230
                $array[$key] = $value->toArray();
231
232
                continue;
233
            }
234
235
            if (! is_array($value)) {
236
                continue;
237
            }
238
239
            $array[$key] = $this->parseArray($value);
240
        }
241
242
        return $array;
243
    }
244
}
245