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

DataTransferObject   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 39
lcom 1
cbo 7
dl 0
loc 256
rs 9.28
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A setPropertyDefaultValue() 0 4 1
A processRemainingProperties() 0 6 2
A getPublicProperties() 0 11 2
A validateProperty() 0 9 4
A setPropertyValue() 0 6 2
A mutateProperty() 0 4 1
A __set() 0 14 4
A __get() 0 4 1
A __construct() 0 4 1
A boot() 0 28 2
A resolveImmutable() 0 6 2
A mutable() 0 6 1
A immutable() 0 6 1
A all() 0 10 2
A only() 0 6 1
A except() 0 11 3
A toArray() 0 17 4
A parseArray() 0 21 5
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 $onlyKeys = [];
25
26
    /** @var Property[] | array */
27
    protected $properties = [];
28
29
    /** @var bool */
30
    protected $immutable = false;
31
32
    public function __construct(array $parameters)
33
    {
34
        $this->boot($parameters);
35
    }
36
37
    /**
38
     * Boot the dto and process all parameters.
39
     * @param array $parameters
40
     * @throws \ReflectionException
41
     */
42
    protected function boot(array $parameters): void
43
    {
44
        $this->resolveImmutable();
45
46
        foreach ($this->getPublicProperties() as $property) {
47
48
            /*
49
             * Do not change the order of the following methods.
50
             * External packages rely on this order.
51
             */
52
53
            $this->setPropertyDefaultValue($property);
54
55
            $property = $this->mutateProperty($property);
56
57
            $this->validateProperty($property, $parameters);
58
59
            $this->setPropertyValue($property, $parameters);
60
61
            /* add the property to an associative array with the name as key */
62
            $this->properties[$property->getName()] = $property;
63
64
            /* remove the property from the value object and parameters array  */
65
            unset($parameters[$property->getName()], $this->{$property->getName()});
66
        }
67
68
        $this->processRemainingProperties($parameters);
69
    }
70
71
    protected function resolveImmutable()
72
    {
73
        if ($this instanceof immutable) {
74
            $this->immutable = true;
75
        }
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 PropertyContract $property
98
     * @param array $parameters
99
     */
100
    protected function validateProperty(PropertyContract $property, array $parameters): void
101
    {
102
        if (! array_key_exists($property->getName(), $parameters)
103
            && is_null($property->getDefault())
104
            && ! $property->nullable()
105
        ) {
106
            throw new UninitialisedPropertyDtoException($property);
107
        }
108
    }
109
110
    /**
111
     * Set the value if it's present in the array.
112
     * @param PropertyContract $property
113
     * @param array $parameters
114
     */
115
    protected function setPropertyValue(PropertyContract $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 PropertyContract $property
125
     */
126
    protected function setPropertyDefaultValue(PropertyContract $property): void
127
    {
128
        $property->setDefault($property->getValueFromReflection($this));
129
    }
130
131
    /**
132
     * Allows to mutate the property before it gets processed.
133
     * @param PropertyContract $property
134
     * @return PropertyContract
135
     */
136
    protected function mutateProperty(PropertyContract $property): PropertyContract
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 UnknownPropertiesDtoException
147
     */
148
    protected function processRemainingProperties(array $parameters)
149
    {
150
        if (count($parameters)) {
151
            throw new UnknownPropertiesDtoException(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 ImmutableDtoException|ImmutablePropertyDtoException|PropertyNotFoundDtoException
161
     */
162
    public function __set($name, $value)
163
    {
164
        if ($this->immutable) {
165
            throw new ImmutableDtoException($name);
166
        }
167
        if (! isset($this->properties[$name])) {
168
            throw new PropertyNotFoundDtoException($name, get_class($this));
169
        }
170
171
        if ($this->properties[$name]->immutable()) {
172
            throw new ImmutablePropertyDtoException($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
    /**
188
     * @return static
189
     */
190
    public function mutable(): DtoContract
191
    {
192
        $this->immutable = false;
193
194
        return $this;
195
    }
196
197
    /**
198
     * @return static
199
     */
200
    public function immutable(): DtoContract
201
    {
202
        $this->immutable = true;
203
204
        return $this;
205
    }
206
207
    public function all(): array
208
    {
209
        $data = [];
210
211
        foreach ($this->properties as $property) {
212
            $data[$property->getName()] = $property->getValue();
213
        }
214
215
        return $data;
216
    }
217
218
    public function only(string ...$keys): DtoContract
219
    {
220
        $this->onlyKeys = array_merge($this->onlyKeys, $keys);
221
222
        return $this;
223
    }
224
225
    public function except(string ...$keys): DtoContract
226
    {
227
        foreach ($keys as $key) {
228
            $property = $this->properties[$key] ?? null;
229
            if (isset($property)) {
230
                $property->setVisible(false);
231
            }
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
252
        return $this->parseArray($array);
253
    }
254
255
    protected function parseArray(array $array): array
256
    {
257
        foreach ($array as $key => $value) {
258
            if (
259
                $value instanceof DataTransferObject
260
                || $value instanceof DataTransferObjectCollection
261
            ) {
262
                $array[$key] = $value->toArray();
263
264
                continue;
265
            }
266
267
            if (! is_array($value)) {
268
                continue;
269
            }
270
271
            $array[$key] = $this->parseArray($value);
272
        }
273
274
        return $array;
275
    }
276
}
277