Passed
Push — master ( 85a044...d13a23 )
by SignpostMarv
12:54
created

Thing   F

Complexity

Total Complexity 62

Size/Duplication

Total Lines 688
Duplicated Lines 0 %

Test Coverage

Coverage 96.52%

Importance

Changes 0
Metric Value
eloc 199
dl 0
loc 688
ccs 194
cts 201
cp 0.9652
rs 3.44
c 0
b 0
f 0
wmc 62

45 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 23 1
A ObtainType() 0 3 1
A ObtainContext() 0 3 1
A SetDisambiguatingDescription() 0 3 1
A GetAdditionalType() 0 3 1
A GetDisambiguatingDescription() 0 3 1
A SetAlternateName() 0 3 1
A SetAdditionalType() 0 3 1
A SetDescription() 0 3 1
A GetAlternateName() 0 3 1
A GetDescription() 0 3 1
A GetUrl() 0 3 1
A DaftObjectFromJsonArrayFromArray() 0 27 3
A GetName() 0 3 1
A SetImage() 0 3 1
A GetSubjectOf() 0 8 1
A DaftObjectExportableProperties() 0 3 1
A GetImage() 0 8 1
A SetIdentifier() 0 3 1
A DaftObjectNullableProperties() 0 19 1
A SetSameAs() 0 3 1
A jsonSerialize() 0 9 2
A SetUrl() 0 3 1
A GetPotentialAction() 0 8 1
A DaftObjectFromJsonArrayFromArrayMapVal() 0 34 6
A SetPotentialAction() 0 3 1
A DaftObjectPublicGetters() 0 18 2
A DaftObjectPublicOrProtectedGetters() 0 18 2
A DaftObjectFromJsonArray() 0 49 4
A GetIdentifier() 0 3 1
A DaftObjectPropertiesWithMultiTypedArraysOfUniqueValues() 0 23 2
A ExpectRetrievedValueIsArray() 0 6 1
A ExpectRetrievedValueIsArrayOfStringsOrPropertyValues() 0 9 1
A SetMainEntityOfPage() 0 3 1
A DaftObjectJsonProperties() 0 3 1
A DaftObjectFromJsonString() 0 15 1
A DaftObjectPublicSetters() 0 18 2
A ExpectRetrievedValueIsArrayOfStrings() 0 8 1
A SetName() 0 3 1
A NudgePropertyWithUniqueBooleans() 0 13 3
A SetSubjectOf() 0 3 1
A ExpectRetrievedValueIsArrayOfStringsOrCreativeWorks() 0 9 1
A DaftObjectProperties() 0 19 1
A GetMainEntityOfPage() 0 3 1
A GetSameAs() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Thing 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 Thing, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftObject\SchemaOrg;
8
9
use InvalidArgumentException;
10
use SignpostMarv\DaftObject\AbstractArrayBackedDaftObject;
11
use SignpostMarv\DaftObject\DaftJson;
12
use SignpostMarv\DaftObject\DaftObjectHasPropertiesWithMultiTypedArraysOfUniqueValues;
13
use SignpostMarv\DaftObject\JsonTypeUtilities;
14
use SignpostMarv\DaftObject\SchemaOrg\CreativeWork\MediaObject\ImageObject;
15
use SignpostMarv\DaftObject\SchemaOrg\Intangible\StructuredValue\PropertyValue;
16
use SignpostMarv\DaftObject\SchemaOrgLookup\LookupInterface;
17
18
/**
19
* @property array<int, string> $additionalType
20
* @property array<int, string> $alternateName
21
* @property array<int, string> $description
22
* @property array<int, string> $disambiguatingDescription
23
* @property array<int, string|PropertyValue> $identifier
24
* @property array<int, string|ImageObject> $image
25
* @property array<int, string|CreativeWork> $mainEntityOfPage
26
* @property array<int, string> $name
27
* @property array<int, Action> $potentialAction
28
* @property array<int, string> $sameAs
29
* @property array<int, CreativeWork|Event> $subjectOf
30
* @property array<int, Action> $potentialAction
31
* @property array<int, string> $url
32
*
33
* @template-implements DaftJson<Thing>
34
*/
35
class Thing extends AbstractArrayBackedDaftObject implements
36
    DaftJson,
37
    DaftObjectHasPropertiesWithMultiTypedArraysOfUniqueValues
38
{
39
    const SCHEMA_ORG_CONTEXT = 'http://schema.org';
40
41
    const SCHEMA_ORG_TYPE = 'Thing';
42
43
    const PROPERTIES = [
44
        '@context',
45
        '@type',
46
        'additionalType',
47
        'alternateName',
48
        'description',
49
        'disambiguatingDescription',
50
        'identifier',
51
        'image',
52
        'mainEntityOfPage',
53
        'name',
54
        'potentialAction',
55
        'sameAs',
56
        'subjectOf',
57
        'url',
58
    ];
59
60
    const PROPERTIES_WITH_MULTI_TYPED_ARRAYS = [
61
        'additionalType' => [
62
            'string',
63
        ],
64
        'alternateName' => [
65
            'string',
66
        ],
67
        'description' => [
68
            'string',
69
        ],
70
        'disambiguatingDescription' => [
71
            'string',
72
        ],
73
        'identifier' => [
74
            'string',
75
            PropertyValue::class,
76
        ],
77
        'image' => [
78
            'string',
79
            ImageObject::class,
80
        ],
81
        'mainEntityOfPage' => [
82
            'string',
83
            CreativeWork::class,
84
        ],
85
        'name' => [
86
            'string',
87
        ],
88
        'potentialAction' => [
89
            Action::class,
90
        ],
91
        'sameAs' => [
92
            'string',
93
        ],
94
        'subjectOf' => [
95
            CreativeWork::class,
96
            Event::class,
97
        ],
98
        'url' => [
99
            'string',
100
        ],
101
    ];
102
103 10220
    public function __construct(array $data = [], bool $writeAll = false)
104
    {
105 10220
        $missing = array_diff(static::DaftObjectProperties(), array_keys($data));
106
107
        /**
108
        * @var array<int, string>
109
        */
110 10220
        $missing = array_combine(
111 10220
            $missing,
112 10220
            array_fill(0, count($missing), [])
113
        );
114
115
        /**
116
        * @var array<string, scalar|array|object|null>
117
        */
118 10220
        $data = array_merge(
119 10220
            $data,
120 10220
            $missing
121
        );
122
123 10220
        unset($data['@context'], $data['@type']);
124
125 10220
        parent::__construct($data, $writeAll);
126 10220
    }
127
128 261
    public function ObtainContext() : string
129
    {
130 261
        return (string) static::SCHEMA_ORG_CONTEXT;
131
    }
132
133 261
    public function ObtainType() : string
134
    {
135 261
        return (string) static::SCHEMA_ORG_TYPE;
136
    }
137
138
    /**
139
    * @return array<int, string>
140
    */
141 520
    public function GetAdditionalType() : array
142
    {
143 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('additionalType');
144
    }
145
146
    /**
147
    * @param array<int, string> $value
148
    */
149 260
    public function SetAdditionalType(array $value) : void
150
    {
151 260
        $this->NudgePropertyValue('additionalType', $value, true);
152 260
    }
153
154
    /**
155
    * @return array<int, string>
156
    */
157 520
    public function GetAlternateName() : array
158
    {
159 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('alternateName');
160
    }
161
162
    /**
163
    * @param array<int, string> $value
164
    */
165 260
    public function SetAlternateName(array $value) : void
166
    {
167 260
        $this->NudgePropertyValue('alternateName', $value, true);
168 260
    }
169
170
    /**
171
    * @return array<int, string>
172
    */
173 520
    public function GetDescription() : array
174
    {
175 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('description');
176
    }
177
178
    /**
179
    * @param array<int, string> $value
180
    */
181 260
    public function SetDescription(array $value) : void
182
    {
183 260
        $this->NudgePropertyValue('description', $value, true);
184 260
    }
185
186
    /**
187
    * @return array<int, string>
188
    */
189 520
    public function GetDisambiguatingDescription() : array
190
    {
191 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('disambiguatingDescription');
192
    }
193
194
    /**
195
    * @param array<int, string> $value
196
    */
197 260
    public function SetDisambiguatingDescription(array $value) : void
198
    {
199 260
        $this->NudgePropertyValue('disambiguatingDescription', $value, true);
200 260
    }
201
202
    /**
203
    * @return array<int, string|PropertyValue>
204
    */
205 521
    public function GetIdentifier() : array
206
    {
207 521
        return $this->ExpectRetrievedValueIsArrayOfStringsOrPropertyValues('identifier');
208
    }
209
210
    /**
211
    * @param array<int, string|PropertyValue> $value
212
    */
213 261
    public function SetIdentifier(array $value) : void
214
    {
215 261
        $this->NudgePropertyValue('identifier', $value, true);
216 261
    }
217
218
    /**
219
    * @return array<int, string|ImageObject>
220
    */
221 520
    public function GetImage() : array
222
    {
223
        /**
224
        * @var array<int, string|ImageObject>
225
        */
226 520
        $out = $this->ExpectRetrievedValueIsArray('image');
227
228 520
        return $out;
229
    }
230
231
    /**
232
    * @param array<int, string|ImageObject> $value
233
    */
234 260
    public function SetImage(array $value) : void
235
    {
236 260
        $this->NudgePropertyValue('image', $value, true);
237 260
    }
238
239
    /**
240
    * @return array<int, string|CreativeWork>
241
    */
242 520
    public function GetMainEntityOfPage() : array
243
    {
244 520
        return $this->ExpectRetrievedValueIsArrayOfStringsOrCreativeWorks('mainEntityOfPage');
245
    }
246
247
    /**
248
    * @param array<int, string|CreativeWork> $value
249
    */
250 260
    public function SetMainEntityOfPage(array $value) : void
251
    {
252 260
        $this->NudgePropertyValue('mainEntityOfPage', $value, true);
253 260
    }
254
255
    /**
256
    * @return array<int, string>
257
    */
258 520
    public function GetName() : array
259
    {
260 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('name');
261
    }
262
263
    /**
264
    * @param array<int, string> $value
265
    */
266 260
    public function SetName(array $value) : void
267
    {
268 260
        $this->NudgePropertyValue('name', $value, true);
269 260
    }
270
271
    /**
272
    * @return array<int, Action>
273
    */
274 520
    public function GetPotentialAction() : array
275
    {
276
        /**
277
        * @var array<int, Action>
278
        */
279 520
        $out = $this->ExpectRetrievedValueIsArray('potentialAction');
280
281 520
        return $out;
282
    }
283
284
    /**
285
    * @param array<int, Action> $value
286
    */
287 260
    public function SetPotentialAction(array $value) : void
288
    {
289 260
        $this->NudgePropertyValue('potentialAction', $value);
290 260
    }
291
292
    /**
293
    * @return array<int, string>
294
    */
295 520
    public function GetSameAs() : array
296
    {
297 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('sameAs');
298
    }
299
300
    /**
301
    * @param array<int, string> $value
302
    */
303 260
    public function SetSameAs(array $value) : void
304
    {
305 260
        $this->NudgePropertyValue('sameAs', $value, true);
306 260
    }
307
308
    /**
309
    * @return array<int, CreativeWork|Event>
310
    */
311 520
    public function GetSubjectOf() : array
312
    {
313
        /**
314
        * @var array<int, CreativeWork|Event>
315
        */
316 520
        $out = $this->ExpectRetrievedValueIsArray('subjectOf');
317
318 520
        return $out;
319
    }
320
321
    /**
322
    * @param array<int, CreativeWork|Event> $value
323
    */
324 260
    public function SetSubjectOf(array $value) : void
325
    {
326 260
        $this->NudgePropertyValue('subjectOf', $value, true);
327 260
    }
328
329
    /**
330
    * @return array<int, string>
331
    */
332 520
    public function GetUrl() : array
333
    {
334 520
        return $this->ExpectRetrievedValueIsArrayOfStrings('url');
335
    }
336
337
    /**
338
    * @param array<int, string> $value
339
    */
340 260
    public function SetUrl(array $value) : void
341
    {
342 260
        $this->NudgePropertyValue('url', $value, true);
343 260
    }
344
345 261
    public function jsonSerialize() : array
346
    {
347 261
        return array_filter(
348 261
            parent::jsonSerialize(),
349
            /**
350
            * @param scalar|array|object|null $val
351
            */
352
            function ($val) : bool {
353 261
                return ! is_array($val) || count($val) > 0;
354 261
            }
355
        );
356
    }
357
358 20654
    public static function DaftObjectProperties() : array
359
    {
360
        /**
361
        * @var array<int, string>
362
        */
363 20654
        $static = static::PROPERTIES;
364
365
        /**
366
        * @var string
367
        *
368
        * @psalm-var class-string<Thing>
369
        */
370 20654
        $static_parent = get_parent_class(static::class);
371
372 20654
        $parent = $static_parent::DaftObjectProperties();
373
374 20654
        return array_unique(array_merge(
375 20654
            $parent,
376 20654
            $static
377
        ));
378
    }
379
380
    /**
381
    * @return array<string, array<int, string>>
382
    */
383 523
    public static function DaftObjectPropertiesWithMultiTypedArraysOfUniqueValues() : array
384
    {
385
        /**
386
        * @var array<string, array<int, string>>
387
        */
388 523
        $static = static::PROPERTIES_WITH_MULTI_TYPED_ARRAYS;
389
390
        /**
391
        * @var string
392
        *
393
        * @psalm-var class-string<Thing>
394
        */
395 523
        $static_parent = get_parent_class(static::class);
396
397 523
        if ($static_parent === get_parent_class(self::class)) {
398 523
            return $static;
399
        }
400
401 521
        $parent = $static_parent::DaftObjectPropertiesWithMultiTypedArraysOfUniqueValues();
402
403 521
        return array_merge(
404 521
            $parent,
405 521
            $static
406
        );
407
    }
408
409 10329
    public static function DaftObjectNullableProperties() : array
410
    {
411
        /**
412
        * @var array<int, string>
413
        */
414 10329
        $static = static::NULLABLE_PROPERTIES;
415
416
        /**
417
        * @var string
418
        *
419
        * @psalm-var class-string<Thing>
420
        */
421 10329
        $static_parent = get_parent_class(static::class);
422
423 10329
        $parent = $static_parent::DaftObjectNullableProperties();
424
425 10329
        return array_unique(array_merge(
426 10329
            $parent,
427 10329
            $static
428
        ));
429
    }
430
431 478
    public static function DaftObjectExportableProperties() : array
432
    {
433 478
        return static::DaftObjectProperties();
434
    }
435
436 521
    public static function DaftObjectJsonProperties() : array
437
    {
438 521
        return static::DaftObjectProperties();
439
    }
440
441 521
    public static function DaftObjectPublicGetters() : array
442
    {
443
        /**
444
        * @var string
445
        *
446
        * @psalm-var class-string<Thing>
447
        */
448 521
        $static_parent = get_parent_class(static::class);
449
450 521
        $static = TypeUtilities::DaftObjectPublicGetters(static::class);
451
452 521
        if ($static_parent === get_parent_class(self::class)) {
453 91
            return $static;
454
        }
455
456 520
        return array_unique(array_merge(
457 520
            TypeUtilities::DaftObjectPublicGetters($static_parent),
458 520
            $static
459
        ));
460
    }
461
462 1
    public static function DaftObjectPublicOrProtectedGetters() : array
463
    {
464
        /**
465
        * @var string
466
        *
467
        * @psalm-var class-string<Thing>
468
        */
469 1
        $static_parent = get_parent_class(static::class);
470
471 1
        $static = TypeUtilities::DaftObjectPublicOrProtectedGetters(static::class);
472
473 1
        if ($static_parent === get_parent_class(self::class)) {
474 1
            return $static;
475
        }
476
477 1
        return array_unique(array_merge(
478 1
            TypeUtilities::DaftObjectPublicOrProtectedGetters($static_parent),
479 1
            $static
480
        ));
481
    }
482
483 261
    public static function DaftObjectPublicSetters() : array
484
    {
485
        /**
486
        * @var string
487
        *
488
        * @psalm-var class-string<Thing>
489
        */
490 261
        $static_parent = get_parent_class(static::class);
491
492 261
        $static = TypeUtilities::DaftObjectPublicSetters(static::class);
493
494 261
        if ($static_parent === get_parent_class(self::class)) {
495 2
            return $static;
496
        }
497
498 260
        return array_unique(array_merge(
499 260
            TypeUtilities::DaftObjectPublicSetters($static_parent),
500 260
            $static
501
        ));
502
    }
503
504
    /**
505
    * @return static
506
    *
507
    * @psalm-return Thing
508
    */
509 261
    public static function DaftObjectFromJsonString(
510
        string $string,
511
        bool $writeAll = self::BOOL_DEFAULT_WRITEALL
512
    ) : DaftJson {
513
        /**
514
        * @var array<string, scalar|(scalar|array|object|null)[]|object|null>
515
        */
516 261
        $decoded = json_decode($string, true);
517
518
        /**
519
        * @var static
520
        */
521 261
        $out = static::DaftObjectFromJsonArray($decoded, $writeAll);
522
523 261
        return $out;
524
    }
525
526
    /**
527
    * @return static
528
    *
529
    * @psalm-return Thing
530
    */
531 262
    public static function DaftObjectFromJsonArray(
532
        array $array,
533
        bool $writeAll = self::BOOL_DEFAULT_WRITEALL
534
    ) : DaftJson {
535 262
        $type = JsonTypeUtilities::ThrowIfNotDaftJson(static::class);
536
537 262
        $multi_type = static::DaftObjectPropertiesWithMultiTypedArraysOfUniqueValues();
538
539 262
        $array_keys = array_keys($array);
540
541 262
        foreach ($array_keys as $k) {
542 262
            if ( ! is_string($k)) {
543 1
                throw new InvalidArgumentException(
544
                    'Argument 1 passed to ' .
545
                    __METHOD__ .
546 262
                    '() must have all-string indices!'
547
                );
548
            }
549
        }
550
551
        /**
552
        * @var array<int, string>
553
        */
554 261
        $array_keys = $array_keys;
555
556 261
        $data = array_combine($array_keys, array_map(
557
            /**
558
            * @param string $k
559
            *
560
            * @return mixed
561
            */
562
            function (string $k) use ($array, $multi_type) {
563 261
                if (is_array($array[$k])) {
564 261
                    return static::DaftObjectFromJsonArrayFromArray($k, $multi_type, $array[$k]);
565
                }
566
567 261
                return $array[$k];
568 261
            },
569 261
            $array_keys
570
        ));
571
572
        /**
573
        * @psalm-var Thing
574
        *
575
        * @var Thing
576
        */
577 261
        $out = new $type($data, $writeAll);
578
579 261
        return $out;
580
    }
581
582
    /**
583
    * @param array<string, array<int, string>> $multi_type
584
    */
585 261
    protected static function DaftObjectFromJsonArrayFromArray(
586
        string $k,
587
        array $multi_type,
588
        array $arr
589
    ) : array {
590 261
        return array_map(
591
            /**
592
            * @param mixed $val
593
            *
594
            * @return mixed
595
            */
596
            function ($val) use ($k, $multi_type) {
597
                if (
598 261
                    is_array($val) &&
599 261
                    isset($val['@context'], $val['@type'], $multi_type[$k])
600
                ) {
601
                    /**
602
                    * @psalm-var array<string, array<array-key, array<array-key, mixed>|scalar|object|null>|scalar|object|null>
603
                    */
604 261
                    $val = $val;
605
606 261
                    return static::DaftObjectFromJsonArrayFromArrayMapVal($val, $multi_type, $k);
607
                }
608
609 261
                return $val;
610 261
            },
611 261
            $arr
612
        );
613
    }
614
615
    /**
616
    * @param array<string, array<int, string>> $multi_type
617
    *
618
    * @psalm-param array<string, array<array-key, array<array-key, mixed>|scalar|object|null>|scalar|object|null> $val
619
    */
620 261
    protected static function DaftObjectFromJsonArrayFromArrayMapVal(
621
        array $val,
622
        array $multi_type,
623
        string $k
624
    ) : Thing {
625 261
        foreach ($multi_type[$k] as $maybe) {
626
            $lookup_class =
627
                '\\SignpostMarv\\DaftObject\\SchemaOrgLookup\\Lookup_' .
628 261
                hash('sha512', $maybe);
629 261
            if (is_a($lookup_class, LookupInterface::class, true)) {
630
                /**
631
                * @psalm-var array<int, class-string<Thing>>
632
                */
633 261
                $maybe_classes = $lookup_class::ObtainClasses();
634
635 261
                foreach ($maybe_classes as $maybe_class) {
636
                    if (
637 261
                        $val['@context'] === $maybe_class::SCHEMA_ORG_CONTEXT &&
638 261
                        $val['@type'] === $maybe_class::SCHEMA_ORG_TYPE
639
                    ) {
640 261
                        return $maybe_class::DaftObjectFromJsonArray($val);
641
                    }
642
                }
643
            }
644
        }
645
646
        throw new InvalidArgumentException(
647
            'Argument 3 (' .
648
            $k .
649
            ') passed to ' .
650
            __METHOD__ .
651
            '() did not correspond to an instance of ' .
652
            Thing::class .
653
            ' as defined in Argument 2!'
654
        );
655
    }
656
657 521
    protected function ExpectRetrievedValueIsArray(string $property) : array
658
    {
659 521
        return TypeUtilities::ExpectRetrievedValueIsArray(
660 521
            $property,
661 521
            $this->RetrievePropertyValueFromData($property),
662 521
            static::class
663
        );
664
    }
665
666
    /**
667
    * @return array<int, string>
668
    */
669 520
    protected function ExpectRetrievedValueIsArrayOfStrings(string $property) : array
670
    {
671
        /**
672
        * @var array<int, string>
673
        */
674 520
        $out = $this->ExpectRetrievedValueIsArray($property);
675
676 520
        return $out;
677
    }
678
679
    /**
680
    * @return array<int, string|PropertyValue>
681
    */
682 521
    protected function ExpectRetrievedValueIsArrayOfStringsOrPropertyValues(
683
        string $property
684
    ) : array {
685
        /**
686
        * @var array<int, string|PropertyValue>
687
        */
688 521
        $out = $this->ExpectRetrievedValueIsArray($property);
689
690 521
        return $out;
691
    }
692
693
    /**
694
    * @return array<int, string|CreativeWork>
695
    */
696 520
    protected function ExpectRetrievedValueIsArrayOfStringsOrCreativeWorks(
697
        string $property
698
    ) : array {
699
        /**
700
        * @var array<int, string|CreativeWork>
701
        */
702 520
        $out = $this->ExpectRetrievedValueIsArray($property);
703
704 520
        return $out;
705
    }
706
707
    /**
708
    * @param array<int, bool> $value
709
    */
710 69
    protected function NudgePropertyWithUniqueBooleans(
711
        string $property,
712
        array $value
713
    ) : void {
714 69
        $replace = [];
715 69
        if (in_array(true, $value, true)) {
716 66
            $replace[] = true;
717
        }
718 69
        if (in_array(false, $value, true)) {
719 68
            $replace[] = false;
720
        }
721
722 69
        $this->NudgePropertyValue($property, $replace);
723 69
    }
724
}
725