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 — master ( 77885b...da55b1 )
by SignpostMarv
04:58
created

RetrievePropertyValueFromDataExpectBoolishOrNull()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 2
rs 10
c 0
b 0
f 0
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, scalar|array|object|null>
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 1152
    public function __construct(array $data = [], bool $writeAll = false)
49
    {
50 1152
        if (true === $writeAll) {
51 192
            foreach ($data as $k => $v) {
52 192
                $this->__set($k, $v);
53
            }
54
        } else {
55 960
            foreach ($data as $k => $v) {
56 300
                $this->data[$k] = $v;
57
            }
58
        }
59 1152
    }
60
61 80
    public function __isset(string $property) : bool
62
    {
63
        return
64 80
            in_array(
65 60
                $property,
66 80
                static::DaftObjectProperties(),
67 80
                DefinitionAssistant::IN_ARRAY_STRICT_MODE
68
            ) &&
69 80
            isset($this->data, $this->data[$property]);
70
    }
71
72 88
    public function ChangedProperties() : array
73
    {
74 88
        return array_keys($this->changedProperties);
75
    }
76
77 88
    public function MakePropertiesUnchanged(string ...$properties) : void
78
    {
79 88
        foreach ($properties as $property) {
80 88
            unset($this->changedProperties[$property]);
81
        }
82 88
    }
83
84 352
    public function HasPropertyChanged(string $property) : bool
85
    {
86 352
        return $this->changedProperties[$property] ?? false;
87
    }
88
89 124
    public function jsonSerialize() : array
90
    {
91
        /**
92
        * @var array<int, string>
93
        */
94 124
        $properties = static::DaftObjectJsonPropertyNames();
95
96
        /**
97
        * @var array<string, string>
98
        */
99 52
        $properties = array_combine($properties, $properties);
100
101 52
        return array_filter(
102 39
            array_map(
103
                /**
104
                * @return scalar|array|object|null
105
                */
106
                function (string $property) {
107 52
                    return $this->DoGetSet($property, false);
108 52
                },
109 26
                $properties
110
            ),
111
            /**
112
            * @param scalar|array|object|null $maybe
113
            */
114
            function ($maybe) : bool {
115 52
                return ! is_null($maybe);
116 52
            }
117
        );
118
    }
119
120
    /**
121
    * @param array<int|string, scalar|(scalar|array|object|null)[]|object|null> $array
122
    */
123 124
    final public static function DaftObjectFromJsonArray(
124
        array $array,
125
        bool $writeAll = self::BOOL_DEFAULT_WRITEALL
126
    ) : DaftJson {
127 124
        $type = JsonTypeUtilities::ThrowIfNotDaftJson(static::class);
128
129 52
        $array = JsonTypeUtilities::ThrowIfJsonDefNotValid($type, $array);
130
131
        /**
132
        * @var array<int, string>
133
        */
134 52
        $props = array_keys($array);
135 52
        $mapper = static::DaftJsonClosure($array, $writeAll);
136
137
        /**
138
        * @var array<int, scalar|object|array|null>
139
        */
140 52
        $vals = array_map($mapper, $props);
141
142 52
        return new $type(array_combine($props, $vals), $writeAll);
143
    }
144
145 196
    public static function DaftObjectFromJsonString(string $string) : DaftJson
146
    {
147
        /**
148
        * @var scalar|array<int|string, scalar|(scalar|array|object|null)[]|object|null>|object|null
149
        */
150 196
        $decoded = json_decode($string, true);
151
152 196
        return JsonTypeUtilities::ThrowIfNotDaftJson(static::class)::DaftObjectFromJsonArray(
153 52
            is_array($decoded) ? $decoded : [$decoded]
154
        );
155
    }
156
157 532
    public function DaftObjectWormPropertyWritten(string $property) : bool
158
    {
159 532
        $wormProperties = $this->wormProperties;
160
161
        return
162 532
            ($this instanceof DaftObjectWorm) &&
163
            (
164 264
                $this->HasPropertyChanged($property) ||
165 532
                isset($wormProperties[$property])
166
            );
167
    }
168
169
    /**
170
    * Retrieve a property from data.
171
    *
172
    * @param string $property the property being retrieved
173
    *
174
    * @throws Exceptions\PropertyNotNullableException if value is not set and $property is not listed as nullabe
175
    *
176
    * @return scalar|array|object|null the property value
177
    */
178 216
    protected function RetrievePropertyValueFromData(string $property)
179
    {
180 216
        $isNullable = in_array(
181 162
            $property,
182 216
            static::DaftObjectNullableProperties(),
183 216
            DefinitionAssistant::IN_ARRAY_STRICT_MODE
184
        );
185
186 216
        if ( ! array_key_exists($property, $this->data) && ! $isNullable) {
187 4
            throw Exceptions\Factory::PropertyNotNullableException(static::class, $property);
188 212
        } elseif ($isNullable) {
189 128
            return $this->data[$property] ?? null;
190
        }
191
192 152
        return $this->data[$property];
193
    }
194
195 76
    protected function RetrievePropertyValueFromDataExpectString(string $property) : string
196
    {
197 76
        return $this->ExpectRetrievedValueIsString(
198 57
            $property,
199 76
            $this->RetrievePropertyValueFromData($property)
200
        );
201
    }
202
203 4
    protected function RetrievePropertyValueFromDataExpectStringOrNull(string $property) : ? string
204
    {
205 4
        $value = $this->RetrievePropertyValueFromData($property);
206
207 4
        if (is_null($value)) {
208 4
            return null;
209
        }
210
211 4
        return $this->ExpectRetrievedValueIsString($property, $value);
212
    }
213
214 4
    protected function RetrievePropertyValueFromDataExpectArray(string $property) : array
215
    {
216 4
        return $this->ExpectRetrievedValueIsArray(
217 3
            $property,
218 4
            $this->RetrievePropertyValueFromData($property)
219
        );
220
    }
221
222 4
    protected function RetrievePropertyValueFromDataExpectArrayOrNull(string $property) : ? array
223
    {
224 4
        $value = $this->RetrievePropertyValueFromData($property);
225
226 4
        if (is_null($value)) {
227 4
            return null;
228
        }
229
230 4
        return $this->ExpectRetrievedValueIsArray($property, $value);
231
    }
232
233 8
    protected function RetrievePropertyValueFromDataExpectIntish(string $property) : int
234
    {
235 8
        return $this->ExpectRetrievedValueIsIntish(
236 6
            $property,
237 8
            $this->RetrievePropertyValueFromData($property)
238
        );
239
    }
240
241 12
    protected function RetrievePropertyValueFromDataExpectIntishOrNull(string $property) : ? int
242
    {
243 12
        $value = $this->RetrievePropertyValueFromData($property);
244
245 12
        if (is_null($value)) {
246 12
            return null;
247
        }
248
249 12
        return $this->ExpectRetrievedValueIsIntish($property, $value);
250
    }
251
252 4
    protected function RetrievePropertyValueFromDataExpectFloatish(string $property) : float
253
    {
254 4
        return $this->ExpectRetrievedValueIsFloatish(
255 3
            $property,
256 4
            $this->RetrievePropertyValueFromData($property)
257
        );
258
    }
259
260 12
    protected function RetrievePropertyValueFromDataExpectFloatishOrNull(string $property) : ? float
261
    {
262 12
        $value = $this->RetrievePropertyValueFromData($property);
263
264 12
        if (is_null($value)) {
265 12
            return null;
266
        }
267
268 12
        return $this->ExpectRetrievedValueIsFloatish($property, $value);
269
    }
270
271 8
    protected function RetrievePropertyValueFromDataExpectBoolish(string $property) : bool
272
    {
273 8
        return $this->ExpectRetrievedValueIsBoolish(
274 6
            $property,
275 8
            $this->RetrievePropertyValueFromData($property)
276
        );
277
    }
278
279 28
    protected function RetrievePropertyValueFromDataExpectBoolishOrNull(string $property) : ? bool
280
    {
281 28
        $value = $this->RetrievePropertyValueFromData($property);
282
283 28
        if (is_null($value)) {
284 28
            return null;
285
        }
286
287 28
        return $this->ExpectRetrievedValueIsBoolish($property, $value);
288
    }
289
290
    /**
291
    * @param scalar|array|object|null $value
292
    */
293 540
    protected function NudgePropertyValue(
294
        string $property,
295
        $value,
296
        bool $autoTrimStrings = self::BOOL_DEFAULT_AUTOTRIMSTRINGS,
297
        bool $throwIfNotUnique = self::BOOL_DEFAULT_THROWIFNOTUNIQUE
298
    ) : void {
299
        /**
300
        * @var array<int, string>
301
        */
302 540
        $nullables = static::DaftObjectNullableProperties();
303
304 540
        $this->MaybeThrowOnNudge($property, $value, $nullables);
305
306 324
        $value = $this->MaybeModifyValueBeforeNudge(
307 243
            $property,
308 162
            $value,
309 162
            $autoTrimStrings,
310 162
            $throwIfNotUnique
311
        );
312
313
        $isChanged = (
314 308
            ! array_key_exists($property, $this->data) ||
315 308
            $this->data[$property] !== $value
316
        );
317
318 308
        $this->data[$property] = $value;
319
320 308
        if ($isChanged && true !== isset($this->changedProperties[$property])) {
321 308
            $this->changedProperties[$property] = $this->wormProperties[$property] = true;
322
        }
323 308
    }
324
325
    /**
326
    * @param scalar|array|object|null $value
327
    */
328 80
    private function ExpectRetrievedValueIsString(string $property, $value) : string
329
    {
330 80
        if ( ! is_string($value)) {
331 4
            throw Exceptions\Factory::PropertyValueNotOfExpectedTypeException(
332 4
                static::class,
333 2
                $property,
334 4
                'string'
335
            );
336
        }
337
338 76
        return $value;
339
    }
340
341
    /**
342
    * @param scalar|array|object|null $value
343
    */
344 8
    private function ExpectRetrievedValueIsArray(string $property, $value) : array
345
    {
346 8
        if ( ! is_array($value)) {
347 4
            throw Exceptions\Factory::PropertyValueNotOfExpectedTypeException(
348 4
                static::class,
349 2
                $property,
350 4
                'array'
351
            );
352
        }
353
354 4
        return $value;
355
    }
356
357
    /**
358
    * @param scalar|array|object|null $value
359
    */
360 20
    private function ExpectRetrievedValueIsIntish(string $property, $value) : int
361
    {
362 20
        if (is_string($value) && ctype_digit($value)) {
363 4
            $value = (int) $value;
364
        }
365
366 20
        if ( ! is_int($value)) {
367 4
            throw Exceptions\Factory::PropertyValueNotOfExpectedTypeException(
368 4
                static::class,
369 2
                $property,
370 4
                'int'
371
            );
372
        }
373
374 16
        return $value;
375
    }
376
377
    /**
378
    * @param scalar|array|object|null $value
379
    */
380 16
    private function ExpectRetrievedValueIsFloatish(string $property, $value) : float
381
    {
382 16
        if (is_string($value) && is_numeric($value)) {
383 4
            $value = (float) $value;
384
        }
385
386 16
        if ( ! is_float($value)) {
387 4
            throw Exceptions\Factory::PropertyValueNotOfExpectedTypeException(
388 4
                static::class,
389 2
                $property,
390 4
                'float'
391
            );
392
        }
393
394 12
        return $value;
395
    }
396
397
    /**
398
    * @param scalar|array|object|null $value
399
    */
400 28
    private function ExpectRetrievedValueIsBoolish(string $property, $value) : bool
401
    {
402 28
        if ('1' === $value || 1 === $value) {
403 8
            return true;
404 20
        } elseif ('0' === $value || 0 === $value) {
405 8
            return false;
406
        }
407
408 12
        if ( ! is_bool($value)) {
409 4
            throw Exceptions\Factory::PropertyValueNotOfExpectedTypeException(
410 4
                static::class,
411 2
                $property,
412 4
                'bool'
413
            );
414
        }
415
416 8
        return $value;
417
    }
418
419
    /**
420
    * @param array<int|string, scalar|array|object|null> $array
421
    */
422 52
    private static function DaftJsonClosure(array $array, bool $writeAll) : Closure
423
    {
424 52
        $jsonDef = static::DaftObjectJsonProperties();
425
426
        return
427
            /**
428
            * @return scalar|array|object|null
429
            */
430
            function (string $prop) use ($array, $jsonDef, $writeAll) {
431
                /**
432
                * @var string|null
433
                */
434 52
                $jsonType = $jsonDef[$prop] ?? null;
435
436 52
                if ( ! is_string($jsonType)) {
437 36
                    return $array[$prop];
438
                }
439
440
                /**
441
                * @var array<int|string, scalar|(scalar|(scalar|array|object|null)[]|object|null)[]|object|null>
442
                */
443 44
                $propVal = (is_array($array[$prop]) ? $array[$prop] : [$array[$prop]]);
444
445 44
                if ('[]' === mb_substr($jsonType, -2)) {
446
                    /**
447
                    * @psalm-var class-string<DaftObject>
448
                    */
449 44
                    $jsonType = mb_substr($jsonType, 0, -2);
450
451 44
                    $jsonType = JsonTypeUtilities::ThrowIfNotJsonType($jsonType);
452
453 44
                    return JsonTypeUtilities::DaftObjectFromJsonTypeArray(
454 33
                        $jsonType,
455 22
                        $prop,
456 22
                        $propVal,
457 22
                        $writeAll
458
                    );
459
                }
460
461
                /**
462
                * @psalm-var class-string<DaftObject>
463
                */
464 28
                $jsonType = $jsonType;
465
466 28
                $jsonType = JsonTypeUtilities::ThrowIfNotJsonType($jsonType);
467
468 28
                return JsonTypeUtilities::DaftJsonFromJsonType($jsonType, $propVal, $writeAll);
469 52
            };
470
    }
471
472
    /**
473
    * @param scalar|array|object|null $value
474
    *
475
    * @return scalar|array|object|null
476
    */
477 324
    private function MaybeModifyValueBeforeNudge(
478
        string $property,
479
        $value,
480
        bool $autoTrimStrings = self::BOOL_DEFAULT_AUTOTRIMSTRINGS,
481
        bool $throwIfNotUnique = self::BOOL_DEFAULT_THROWIFNOTUNIQUE
482
    ) {
483 324
        $spec = null;
484
485
        if (
486 324
            is_a(
487 324
                static::class,
488 324
                DaftObjectHasPropertiesWithMultiTypedArraysOfUniqueValues::class,
489 324
                true
490
            )
491
        ) {
492
            $spec = (
493 24
                static::DaftObjectPropertiesWithMultiTypedArraysOfUniqueValues()[$property] ?? null
494
            );
495
        }
496
497 324
        if (is_array($spec)) {
498 20
            $value = DefinitionAssistant::MaybeThrowIfValueDoesNotMatchMultiTypedArray(
499 15
                $autoTrimStrings,
500 10
                $throwIfNotUnique,
501 10
                $value,
502 8
                ...$spec
503
            );
504
        }
505
506 308
        if (is_string($value) && $autoTrimStrings) {
507 4
            $value = trim($value);
508
        }
509
510 308
        return $value;
511
    }
512
513
    /**
514
    * @see AbstractArrayBackedDaftObject::NudgePropertyValue()
515
    */
516 540
    private function MaybeThrowForPropertyOnNudge(string $property) : string
517
    {
518 540
        $properties = static::DaftObjectProperties();
519
520 540
        if ( ! in_array($property, $properties, DefinitionAssistant::IN_ARRAY_STRICT_MODE)) {
521 8
            throw Exceptions\Factory::UndefinedPropertyException(static::class, $property);
522 532
        } elseif ($this->DaftObjectWormPropertyWritten($property)) {
523 192
            throw Exceptions\Factory::PropertyNotRewriteableException(static::class, $property);
524
        }
525
526 532
        return $property;
527
    }
528
529
    /**
530
    * @param scalar|array|object|null $value
531
    *
532
    * @see AbstractArrayBackedDaftObject::NudgePropertyValue()
533
    */
534 540
    private function MaybeThrowOnNudge(string $property, $value, array $properties) : void
535
    {
536 540
        $property = $this->MaybeThrowForPropertyOnNudge($property);
537
538
        if (
539 532
            true === is_null($value) &&
540 474
            ! in_array($property, $properties, DefinitionAssistant::IN_ARRAY_STRICT_MODE)
541
        ) {
542 208
            throw Exceptions\Factory::PropertyNotNullableException(static::class, $property);
543
        }
544 324
    }
545
}
546