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.
Passed
Pull Request — master (#56)
by Arthur
02:07 queued 45s
created

DataTransferObject   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 71
dl 0
loc 244
rs 9.36
c 0
b 0
f 0
wmc 38

17 Methods

Rating   Name   Duplication   Size   Complexity  
A setPropertyDefaultValue() 0 3 1
A toArray() 0 16 4
A immutable() 0 5 1
A boot() 0 27 2
A __construct() 0 3 1
A mutateProperty() 0 3 1
A getPublicProperties() 0 10 2
A only() 0 5 1
A setPropertyValue() 0 4 2
A resolveImmutable() 0 4 2
A processRemainingProperties() 0 4 2
A all() 0 9 2
A __get() 0 3 1
A parseArray() 0 20 5
A except() 0 10 3
A __set() 0 13 4
A validateProperty() 0 7 4
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()] = new Property($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 immutable(): DtoContract
191
    {
192
        $this->immutable = true;
193
194
        return $this;
195
    }
196
197
    public function all(): array
198
    {
199
        $data = [];
200
201
        foreach ($this->properties as $property) {
202
            $data[$property->getName()] = $property->getValue();
203
        }
204
205
        return $data;
206
    }
207
208
    public function only(string ...$keys): DtoContract
209
    {
210
        $this->onlyKeys = array_merge($this->onlyKeys, $keys);
211
212
        return $this;
213
    }
214
215
    public function except(string ...$keys): DtoContract
216
    {
217
        foreach ($keys as $key) {
218
            $property = $this->properties[$key] ?? null;
219
            if (isset($property)) {
220
                $property->setVisible(false);
221
            }
222
        }
223
224
        return $this;
225
    }
226
227
    public function toArray(): array
228
    {
229
        $data = $this->all();
230
        $array = [];
231
232
        if (count($this->onlyKeys)) {
233
            $array = array_intersect_key($data, array_flip((array) $this->onlyKeys));
234
        } else {
235
            foreach ($data as $key => $propertyValue) {
236
                if ($this->properties[$key]->isVisible()) {
237
                    $array[$key] = $propertyValue;
238
                }
239
            }
240
        }
241
242
        return $this->parseArray($array);
243
    }
244
245
    protected function parseArray(array $array): array
246
    {
247
        foreach ($array as $key => $value) {
248
            if (
249
                $value instanceof DataTransferObject
250
                || $value instanceof DataTransferObjectCollection
251
            ) {
252
                $array[$key] = $value->toArray();
253
254
                continue;
255
            }
256
257
            if (! is_array($value)) {
258
                continue;
259
            }
260
261
            $array[$key] = $this->parseArray($value);
262
        }
263
264
        return $array;
265
    }
266
}
267