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
Push — object-only ( 708468...98fa5f )
by SignpostMarv
10:10
created

AbstractArrayBackedDaftObject   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 319
Duplicated Lines 0 %

Test Coverage

Coverage 93.1%

Importance

Changes 0
Metric Value
wmc 40
eloc 114
dl 0
loc 319
ccs 108
cts 116
cp 0.931
rs 9.2
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A MakePropertiesUnchanged() 0 4 2
A DaftObjectFromJsonArray() 0 20 1
A NudgePropertyValue() 0 29 4
A __isset() 0 9 2
A jsonSerialize() 0 27 1
A DaftObjectFromJsonString() 0 9 2
A ChangedProperties() 0 3 1
A RetrievePropertyValueFromData() 0 15 4
A DaftObjectWormPropertyWritten() 0 9 3
A __construct() 0 9 4
A HasPropertyChanged() 0 3 1
A DaftJsonClosure() 0 33 4
A MaybeThrowOnNudge() 0 9 3
A MaybeModifyValueBeforeNudge() 0 34 5
A MaybeThrowForPropertyOnNudge() 0 11 3

How to fix   Complexity   

Complex Class

Complex classes like AbstractArrayBackedDaftObject often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AbstractArrayBackedDaftObject, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
* Base daft objects.
4
*
5
* @author SignpostMarv
6
*/
7
declare(strict_types=1);
8
9
namespace SignpostMarv\DaftObject;
10
11
use Closure;
12
13
/**
14
* Array-backed daft objects.
15
*/
16
abstract class AbstractArrayBackedDaftObject extends AbstractDaftObject implements DaftObjectCreatedByArray
17
{
18
    const BOOL_DEFAULT_WRITEALL = false;
19
20
    const BOOL_DEFAULT_AUTOTRIMSTRINGS = false;
21
22
    const BOOL_DEFAULT_THROWIFNOTUNIQUE = false;
23
24
    /**
25
    * data for this instance.
26
    *
27
    * @var array<string, mixed>
28
    */
29
    private $data = [];
30
31
    /**
32
    * List of changed properties.
33
    *
34
    * @var array<string, bool>
35
    */
36
    private $changedProperties = [];
37
38
    /**
39
    * List of changed properties, for write-once read-many.
40
    *
41
    * @var array<string, bool>
42
    */
43
    private $wormProperties = [];
44
45
    /**
46
    * @param array<string, scalar|array|object|null> $data
47
    */
48 320
    public function __construct(array $data = [], bool $writeAll = false)
49
    {
50 320
        if (true === $writeAll) {
51 124
            foreach ($data as $k => $v) {
52 124
                $this->__set($k, $v);
53
            }
54
        } else {
55 196
            foreach ($data as $k => $v) {
56 92
                $this->data[$k] = $v;
57
            }
58
        }
59 312
    }
60
61 44
    public function __isset(string $property) : bool
62
    {
63
        return
64 44
            in_array(
65 33
                $property,
66 44
                static::DaftObjectProperties(),
67 44
                DefinitionAssistant::IN_ARRAY_STRICT_MODE
68
            ) &&
69 44
            isset($this->data, $this->data[$property]);
70
    }
71
72 36
    public function ChangedProperties() : array
73
    {
74 36
        return array_keys($this->changedProperties);
75
    }
76
77 52
    public function MakePropertiesUnchanged(string ...$properties) : void
78
    {
79 52
        foreach ($properties as $property) {
80 52
            unset($this->changedProperties[$property]);
81
        }
82 52
    }
83
84 196
    public function HasPropertyChanged(string $property) : bool
85
    {
86 196
        return $this->changedProperties[$property] ?? false;
87
    }
88
89 40
    public function jsonSerialize() : array
90
    {
91
        /**
92
        * @var array<int, string>
93
        */
94 40
        $properties = static::DaftObjectJsonPropertyNames();
95
96
        /**
97
        * @var array<string, string>
98
        */
99 4
        $properties = array_combine($properties, $properties);
100
101 4
        return array_filter(
102 3
            array_map(
103
                /**
104
                * @return mixed
105
                */
106
                function (string $property) {
107 4
                    return $this->DoGetSet($property, false);
108 4
                },
109 2
                $properties
110
            ),
111
            /**
112
            * @param mixed $maybe
113
            */
114
            function ($maybe) : bool {
115 4
                return ! is_null($maybe);
116 4
            }
117
        );
118
    }
119
120 48
    final public static function DaftObjectFromJsonArray(
121
        array $array,
122
        bool $writeAll = self::BOOL_DEFAULT_WRITEALL
123
    ) : DaftJson {
124 48
        $type = JsonTypeUtilities::ThrowIfNotDaftJson(static::class);
125
126 12
        $array = JsonTypeUtilities::ThrowIfJsonDefNotValid($type, $array);
127
128
        /**
129
        * @var array<int, string>
130
        */
131 12
        $props = array_keys($array);
132 12
        $mapper = static::DaftJsonClosure($array, $writeAll);
133
134
        /**
135
        * @var array<int, scalar|object|array|null>
136
        */
137 12
        $vals = array_map($mapper, $props);
138
139 8
        return new $type(array_combine($props, $vals), $writeAll);
140
    }
141
142 76
    public static function DaftObjectFromJsonString(string $string) : DaftJson
143
    {
144
        /**
145
        * @var scalar|array|object|null
146
        */
147 76
        $decoded = json_decode($string, true);
148
149 76
        return JsonTypeUtilities::ThrowIfNotDaftJson(static::class)::DaftObjectFromJsonArray(
150 4
            is_array($decoded) ? $decoded : [$decoded]
151
        );
152
    }
153
154 264
    public function DaftObjectWormPropertyWritten(string $property) : bool
155
    {
156 264
        $wormProperties = $this->wormProperties;
157
158
        return
159 264
            ($this instanceof DaftObjectWorm) &&
160
            (
161 136
                $this->HasPropertyChanged($property) ||
162 264
                isset($wormProperties[$property])
163
            );
164
    }
165
166
    /**
167
    * Retrieve a property from data.
168
    *
169
    * @param string $property the property being retrieved
170
    *
171
    * @throws PropertyNotNullableException if value is not set and $property is not listed as nullabe
172
    *
173
    * @return mixed the property value
174
    */
175 52
    protected function RetrievePropertyValueFromData(string $property)
176
    {
177 52
        $isNullable = in_array(
178 39
            $property,
179 52
            static::DaftObjectNullableProperties(),
180 52
            DefinitionAssistant::IN_ARRAY_STRICT_MODE
181
        );
182
183 52
        if ( ! array_key_exists($property, $this->data) && ! $isNullable) {
184 4
            throw new PropertyNotNullableException(static::class, $property);
185 48
        } elseif ($isNullable) {
186 12
            return $this->data[$property] ?? null;
187
        }
188
189 48
        return $this->data[$property];
190
    }
191
192
    /**
193
    * @param scalar|array|object|null $value
194
    */
195 264
    protected function NudgePropertyValue(
196
        string $property,
197
        $value,
198
        bool $autoTrimStrings = self::BOOL_DEFAULT_AUTOTRIMSTRINGS,
199
        bool $throwIfNotUnique = self::BOOL_DEFAULT_THROWIFNOTUNIQUE
200
    ) : void {
201
        /**
202
        * @var array<int, string>
203
        */
204 264
        $nullables = static::DaftObjectNullableProperties();
205
206 264
        $this->MaybeThrowOnNudge($property, $value, $nullables);
207
208 180
        $value = $this->MaybeModifyValueBeforeNudge(
209 135
            $property,
210 90
            $value,
211 90
            $autoTrimStrings,
212 90
            $throwIfNotUnique
213
        );
214
215
        $isChanged = (
216 164
            ! array_key_exists($property, $this->data) ||
217 164
            $this->data[$property] !== $value
218
        );
219
220 164
        $this->data[$property] = $value;
221
222 164
        if ($isChanged && true !== isset($this->changedProperties[$property])) {
223 164
            $this->changedProperties[$property] = $this->wormProperties[$property] = true;
224
        }
225 164
    }
226
227 12
    private static function DaftJsonClosure(array $array, bool $writeAll) : Closure
228
    {
229 12
        $jsonDef = static::DaftObjectJsonProperties();
230
231
        return
232
            /**
233
            * @return mixed
234
            */
235
            function (string $prop) use ($array, $jsonDef, $writeAll) {
236
                /**
237
                * @var string|null
238
                */
239 8
                $jsonType = $jsonDef[$prop] ?? null;
240
241 8
                if ( ! is_string($jsonType)) {
242 4
                    return $array[$prop];
243
                }
244
245 4
                $propVal = (is_array($array[$prop]) ? $array[$prop] : [$array[$prop]]);
246
247 4
                if ('[]' === mb_substr($jsonType, -2)) {
248 4
                    return JsonTypeUtilities::DaftObjectFromJsonTypeArray(
249 4
                        JsonTypeUtilities::ThrowIfNotJsonType(mb_substr($jsonType, 0, -2)),
250
                        $prop,
251
                        $propVal,
252
                        $writeAll
253
                    );
254
                }
255
256
                return JsonTypeUtilities::DaftJsonFromJsonType(
257
                    JsonTypeUtilities::ThrowIfNotJsonType($jsonType),
258
                    $propVal,
259
                    $writeAll
260
                );
261 12
            };
262
    }
263
264
    /**
265
    * @param scalar|array|object|null $value
266
    *
267
    * @return scalar|array|object|null
268
    */
269 180
    private function MaybeModifyValueBeforeNudge(
270
        string $property,
271
        $value,
272
        bool $autoTrimStrings = self::BOOL_DEFAULT_AUTOTRIMSTRINGS,
273
        bool $throwIfNotUnique = self::BOOL_DEFAULT_THROWIFNOTUNIQUE
274
    ) {
275 180
        $spec = null;
276
277
        if (
278 180
            is_a(
279 180
                static::class,
280 180
                DaftObjectHasPropertiesWithMultiTypedArraysOfUniqueValues::class,
281 180
                true
282
            )
283
        ) {
284
            $spec = (
285 32
                static::DaftObjectPropertiesWithMultiTypedArraysOfUniqueValues()[$property] ?? null
286
            );
287
        }
288
289 180
        if (is_array($spec)) {
290 28
            $value = DefinitionAssistant::MaybeThrowIfValueDoesNotMatchMultiTypedArray(
291 21
                $autoTrimStrings,
292 21
                $throwIfNotUnique,
293 21
                $value,
294 16
                ...$spec
295
            );
296
        }
297
298 164
        if (is_string($value) && $autoTrimStrings) {
299 4
            $value = trim($value);
300
        }
301
302 164
        return $value;
303
    }
304
305
    /**
306
    * @see AbstractArrayBackedDaftObject::NudgePropertyValue()
307
    */
308 264
    private function MaybeThrowForPropertyOnNudge(string $property) : string
309
    {
310 264
        $properties = static::DaftObjectProperties();
311
312 264
        if ( ! in_array($property, $properties, DefinitionAssistant::IN_ARRAY_STRICT_MODE)) {
313
            throw new UndefinedPropertyException(static::class, $property);
314 264
        } elseif ($this->DaftObjectWormPropertyWritten($property)) {
315 100
            throw new PropertyNotRewriteableException(static::class, $property);
316
        }
317
318 264
        return $property;
319
    }
320
321
    /**
322
    * @param mixed $value
323
    *
324
    * @see AbstractArrayBackedDaftObject::NudgePropertyValue()
325
    */
326 264
    private function MaybeThrowOnNudge(string $property, $value, array $properties) : void
327
    {
328 264
        $property = $this->MaybeThrowForPropertyOnNudge($property);
329
330
        if (
331 264
            true === is_null($value) &&
332 230
            ! in_array($property, $properties, DefinitionAssistant::IN_ARRAY_STRICT_MODE)
333
        ) {
334 84
            throw new PropertyNotNullableException(static::class, $property);
335
        }
336 180
    }
337
}
338