Passed
Push — master ( 5a6427...d99853 )
by SignpostMarv
03:56
created

Thing::NudgePropertyWithUniqueTrimmedStrings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.351

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 3
dl 0
loc 19
ccs 5
cts 9
cp 0.5556
crap 2.351
rs 9.9666
c 0
b 0
f 0
1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftObject\SchemaOrg;
8
9
use BadMethodCallException;
10
use InvalidArgumentException;
11
use SignpostMarv\DaftObject\AbstractArrayBackedDaftObject;
12
use SignpostMarv\DaftObject\DaftJson;
13
use SignpostMarv\DaftObject\DaftObjectHasPropertiesWithMultiTypedArraysOfUniqueValues;
14
use SignpostMarv\DaftObject\JsonTypeUtilities;
15
use SignpostMarv\DaftObject\SchemaOrg\CreativeWork\MediaObject\ImageObject;
16
use SignpostMarv\DaftObject\SchemaOrg\DataTypes\Date;
17
use SignpostMarv\DaftObject\SchemaOrg\DataTypes\DateTime;
18
use SignpostMarv\DaftObject\SchemaOrg\Intangible\StructuredValue\ContactPoint;
19
use SignpostMarv\DaftObject\SchemaOrg\Intangible\StructuredValue\PropertyValue;
20
use SignpostMarv\DaftObject\TypeUtilities;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, SignpostMarv\DaftObject\SchemaOrg\TypeUtilities. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

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

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

742
        /** @scrutinizer ignore-unused */ string ...$implementation

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
743
    ) : void {
744
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
745
    }
746
747
    /**
748
    * @param array<int, string|Thing|DataTypes\DataType> $value
749
    *
750
    * @psalm-param class-string<Thing>|class-string<DataTypes\DataType> ...$implementation
751
    */
752 1
    protected function NudgePropertyWithUniqueTrimmedStringsOrThings(
753
        string $property,
754
        string $method,
755
        array $value,
756
        string ...$implementation
0 ignored issues
show
Unused Code introduced by
The parameter $implementation is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

756
        /** @scrutinizer ignore-unused */ string ...$implementation

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
757
    ) : void {
758 1
        $initialCount = count($value);
759
760
        /**
761
        * @var array<int, string|Thing|DataTypes\DataType>
762
        */
763 1
        $value = array_values(array_filter(
764 1
            array_map(
765
                /**
766
                * @param string|Thing|DataTypes\DataType $val
767
                *
768
                * @return string|Thing|DataTypes\DataType
769
                */
770
                function ($val) {
771
                    return is_string($val) ? trim($val) : $val;
772 1
                },
773 1
                $value
774
            ),
775
            /**
776
            * @param string|Thing|DataTypes\DataType $maybe
777
            */
778
            function ($maybe) : bool {
779
                return '' !== $maybe;
780 1
            }
781
        ));
782
783 1
        if (count($value) !== $initialCount) {
784
            throw new InvalidArgumentException(
785
                'Arguments passed to ' .
786
                __METHOD__ .
787
                ' must be strings with no trailing whitespace or instances of ' .
788
                Thing::class
789
            );
790
        }
791
792 1
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
793 1
    }
794
795
    /**
796
    * @param array<int, int|float|string|Thing|DataTypes\DataType> $value
797
    *
798
    * @psalm-param class-string<Thing>|class-string<DataTypes\DataType> ...$implementation
799
    */
800
    protected function NudgePropertyWithUniqueNumericsOrThings(
801
        string $property,
802
        string $method,
803
        array $value,
804
        string ...$implementation
0 ignored issues
show
Unused Code introduced by
The parameter $implementation is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

804
        /** @scrutinizer ignore-unused */ string ...$implementation

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
805
    ) : void {
806
        $initialCount = count($value);
807
808
        /**
809
        * @var array<int, string|Thing|DataTypes\DataType>
810
        */
811
        $value = array_values(
812
            array_map(
813
                /**
814
                * @param string|int|float|Thing|DataTypes\DataType $val
815
                *
816
                * @return int|float|Thing|DataTypes\DataType
817
                */
818
                function ($val) {
819
                    return
820
                        is_string($val)
821
                            ? (
822
                                ctype_digit($val)
823
                                    ? (int) $val
824
                                    : (float) $val
825
                            )
826
                            : $val;
827
                },
828
                $value
829
            )
830
        );
831
832
        if (count($value) !== $initialCount) {
833
            throw new InvalidArgumentException(
834
                'Arguments passed to ' .
835
                __METHOD__ .
836
                ' must be numerics or instances of ' .
837
                Thing::class
838
            );
839
        }
840
841
        $this->NudgePropertyWithUniqueValues($property, $method, $value, SORT_NUMERIC);
842
    }
843
844
    /**
845
    * @param array<int, string> $value
846
    */
847 1
    protected function NudgePropertyWithUniqueTrimmedStringsMightNotBeString(
848
        string $property,
849
        string $method,
850
        array $value
851
    ) : void {
852 1
        $initialCount = count($value);
853
854
        /**
855
        * @var array<int, string>
856
        */
857 1
        $value = array_filter($value, 'is_string');
858
859 1
        if (count($value) !== $initialCount) {
860
            throw new InvalidArgumentException(
861
                'Argument 1 passed to ' .
862
                $method .
863
                ' must be an array of strings!'
864
            );
865
        }
866
867
        $value = array_filter(array_map('trim', $value), function (string $maybe) : bool {
868
            return '' !== $maybe;
869 1
        });
870
871 1
        if ($initialCount !== count($value)) {
872
            throw new InvalidArgumentException(
873
                'Arguments passed to ' .
874
                $method .
875
                ' must not have trailing whitespace!'
876
            );
877
        }
878
879 1
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
880 1
    }
881
882
    /**
883
    * @param array<int, int|float|string> $value
884
    */
885
    protected function NudgePropertyWithUniqueTrimmedStringsNumericsMightNotBeStringsOrNumerics(
886
        string $property,
887
        string $method,
888
        array $value
889
    ) : void {
890
        $initialCount = count($value);
891
892
        /**
893
        * @var array<int, string|float|int>
894
        */
895
        $value = array_filter(
896
            $value,
897
            /**
898
            * @param mixed $maybe
899
            */
900
            function ($maybe) : bool {
901
                return is_string($maybe) || is_numeric($maybe);
902
            }
903
        );
904
905
        if (count($value) !== $initialCount) {
906
            throw new InvalidArgumentException(
907
                'Argument 1 passed to ' .
908
                $method .
909
                ' must be an array of numerics!'
910
            );
911
        }
912
913
        /**
914
        * @var array<int, string|int|float>
915
        */
916
        $value = array_unique(
917
            array_map(
918
                /**
919
                * @param string|float|int $val
920
                *
921
                * @return string|float|int
922
                */
923
                function ($val) {
924
                    return
925
                        is_string($val)
926
                            ? (
927
                                ctype_digit($val)
928
                                    ? (int) $val
929
                                    : (
930
                                        is_numeric($val)
931
                                            ? (float) $val
932
                                            : trim($val)
933
                                    )
934
                            )
935
                            : $val;
936
                },
937
                $value
938
            ),
939
            SORT_NUMERIC
940
        );
941
942
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
943
    }
944
945
    /**
946
    * @param array<int, int> $value
947
    */
948
    protected function NudgePropertyWithUniqueIntegers(
949
        string $property,
950
        string $method,
951
        array $value
952
    ) : void {
953
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
954
    }
955
956
    /**
957
    * @param array<int, int|float|string> $value
958
    */
959 3
    protected function NudgePropertyWithUniqueIntegersOrFloats(
960
        string $property,
961
        string $method,
962
        array $value
963
    ) : void {
964 3
        $initialCount = count($value);
965
966
        /**
967
        * @var array<int, int|float>
968
        */
969 3
        $value = array_map(
970
            /**
971
            * @param int|float|string $val
972
            *
973
            * @return int|float
974
            */
975
            function ($val) {
976
                return
977 3
                    (is_int($val) || is_float($val))
978 3
                        ? $val
979
                        : (
980
                            ctype_digit($val)
981
                                ? (int) $val
982 3
                                : (float) $val
983
                        );
984 3
            },
985 3
            array_filter($value, 'is_numeric')
986
        );
987
988 3
        if (count($value) !== $initialCount) {
989
            throw new InvalidArgumentException(
990
                'Argument 1 passed to ' .
991
                $method .
992
                ' must be a numeric list!'
993
            );
994
        }
995
996 3
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
997 3
    }
998
999
    /**
1000
    * @param array<int, bool> $value
1001
    */
1002
    protected function NudgePropertyWithUniqueBooleans(
1003
        string $property,
1004
        string $method,
1005
        array $value
1006
    ) : void {
1007
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
1008
    }
1009
1010
    /**
1011
    * @param array<int, int|string> $value
1012
    */
1013
    protected function NudgePropertWithUniqueIntegersOrTrimmedStrings(
1014
        string $property,
1015
        string $method,
1016
        array $value
1017
    ) : void {
1018
        $initialCount = count($value);
1019
1020
        $value = array_map(
1021
            /**
1022
            * @param int|string $val
1023
            *
1024
            * @return int|string
1025
            */
1026
            function ($val) {
1027
                return is_string($val) ? trim($val) : $val;
1028
            },
1029
            array_filter(
1030
                $value,
1031
                /**
1032
                * @param mixed $maybe
1033
                */
1034
                function ($maybe) : bool {
1035
                    return is_string($maybe) || is_int($maybe);
1036
                }
1037
            )
1038
        );
1039
1040
        if (count($value) !== $initialCount) {
1041
            throw new InvalidArgumentException(
1042
                'Argument 1 passed to ' .
1043
                $method .
1044
                ' must be a list of integers & strings!'
1045
            );
1046
        }
1047
1048
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
1049
    }
1050
1051
    /**
1052
    * @param array<int, scalar|array|object|null> $value
1053
    */
1054 3
    protected function NudgePropertyWithUniqueValues(
1055
        string $property,
1056
        string $method,
1057
        array $value,
1058
        int $sort_flags = SORT_REGULAR
1059
    ) : void {
1060 3
        $initialCount = count($value);
1061
1062 3
        $value = array_values(array_unique($value, $sort_flags));
1063
1064 3
        if ($initialCount !== count($value)) {
1065
            throw new InvalidArgumentException(
1066
                'Arguments passed to ' .
1067
                $method .
1068
                ' must be unique!'
1069
            );
1070
        }
1071
1072 3
        $this->NudgePropertyValue($property, $value);
1073 3
    }
1074
1075
    /**
1076
    * @param array<int, Date> $value
1077
    */
1078
    protected function NudgePropertyWithUniqueDates(
1079
        string $property,
1080
        string $method,
1081
        array $value
1082
    ) : void {
1083
        $this->NudgePropertyWithUniqueValuesOfThings($property, $method, $value, Date::class);
1084
    }
1085
1086
    /**
1087
    * @param array<int, DateTime> $value
1088
    */
1089
    protected function NudgePropertyWithUniqueDateTimes(
1090
        string $property,
1091
        string $method,
1092
        array $value
1093
    ) : void {
1094
        $this->NudgePropertyWithUniqueValuesOfThings($property, $method, $value, DateTime::class);
1095
    }
1096
1097
    /**
1098
    * @param array<int, Date|DateTime> $value
1099
    */
1100
    protected function NudgePropertyWithUniqueDatesOrDateTimes(
1101
        string $property,
1102
        string $method,
1103
        array $value
1104
    ) : void {
1105
        $this->NudgePropertyWithUniqueValuesOfThings(
1106
            $property,
1107
            $method,
1108
            $value,
1109
            Date::class,
1110
            DateTime::class
1111
        );
1112
    }
1113
1114
    /**
1115
    * @param array<int, Person> $value
1116
    */
1117
    protected function NudgePropertyWithUniquePersons(
1118
        string $property,
1119
        string $method,
1120
        array $value
1121
    ) : void {
1122
        $this->NudgePropertyWithUniqueValuesOfThings(
1123
            $property,
1124
            $method,
1125
            $value,
1126
            Person::class
1127
        );
1128
    }
1129
1130
    /**
1131
    * @param array<int, Organization|Person> $value
1132
    */
1133
    protected function NudgePropertyWithUniqueOrganizationsOrPersons(
1134
        string $property,
1135
        string $method,
1136
        array $value
1137
    ) : void {
1138
        $this->NudgePropertyWithUniqueValuesOfThings(
1139
            $property,
1140
            $method,
1141
            $value,
1142
            Organization::class,
1143
            Person::class
1144
        );
1145
    }
1146
1147
    /**
1148
    * @param array<int, Organization> $value
1149
    */
1150
    protected function NudgePropertyWithUniqueOrganizations(
1151
        string $property,
1152
        string $method,
1153
        array $value
1154
    ) : void {
1155
        $this->NudgePropertyWithUniqueValuesOfThings(
1156
            $property,
1157
            $method,
1158
            $value,
1159
            Organization::class
1160
        );
1161
    }
1162
1163
    /**
1164
    * @param array<int, Event> $value
1165
    */
1166
    protected function NudgePropertyWithUniqueEvents(
1167
        string $property,
1168
        string $method,
1169
        array $value
1170
    ) : void {
1171
        $this->NudgePropertyWithUniqueValuesOfThings(
1172
            $property,
1173
            $method,
1174
            $value,
1175
            Event::class
1176
        );
1177
    }
1178
1179
    /**
1180
    * @param array<int, Place> $value
1181
    */
1182
    protected function NudgePropertyValueWithUniquePlaces(
1183
        string $property,
1184
        string $method,
0 ignored issues
show
Unused Code introduced by
The parameter $method is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1184
        /** @scrutinizer ignore-unused */ string $method,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1185
        array $value
1186
    ) : void {
1187
        $this->NudgePropertyWithUniqueValuesOfThings(
1188
            $property,
1189
            __METHOD__,
1190
            $value,
1191
            Place::class
1192
        );
1193
    }
1194
1195
    /**
1196
    * @param array<int, ContactPoint|Place> $value
1197
    */
1198
    protected function NudgePropertyValueWithUniqueContactPointsOrPlaces(
1199
        string $property,
1200
        string $method,
0 ignored issues
show
Unused Code introduced by
The parameter $method is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1200
        /** @scrutinizer ignore-unused */ string $method,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1201
        array $value
1202
    ) : void {
1203
        $this->NudgePropertyWithUniqueValuesOfThings(
1204
            $property,
1205
            __METHOD__,
1206
            $value,
1207
            ContactPoint::class,
1208
            Place::class
1209
        );
1210
    }
1211
1212
    /**
1213
    * @param array<int, Thing|DataTypes\DataType> $value
1214
    *
1215
    * @psalm-param class-string<Thing>|class-string<DataTypes\DataType> ...$validThings
1216
    */
1217 3
    protected function NudgePropertyWithUniqueValuesOfThings(
1218
        string $property,
1219
        string $method,
1220
        array $value,
1221
        string ...$validThings
1222
    ) : void {
1223 3
        $initialCount = count($validThings);
1224
1225 3
        if (0 === $initialCount) {
1226
            throw new BadMethodCallException(
1227
                'Argument 4 of ' .
1228
                __METHOD__ .
1229
                ' is required!'
1230
            );
1231 3
        } elseif (count($validThings) !== $initialCount) {
1232
            throw new InvalidArgumentException(
1233
                'Arguments 4+ passed to ' .
1234
                __METHOD__ .
1235
                ' must be implementations of ' .
1236
                Thing::class .
1237
                '!'
1238
            );
1239
        }
1240
1241 3
        $initialCount = count($value);
1242
1243
        /**
1244
        * @var array<int, Thing|DataTypes\DataType>
1245
        */
1246 3
        $value = array_filter(
1247 3
            $value,
1248
            /**
1249
            * @param Thing|DataTypes\DataType $maybe
1250
            */
1251
            function ($maybe) use ($validThings) : bool {
1252 2
                foreach ($validThings as $thing) {
1253 2
                    if (is_a($maybe, $thing, true)) {
1254 2
                        return true;
1255
                    }
1256
                }
1257
1258
                return false;
1259 3
            }
1260
        );
1261
1262 3
        if (count($value) !== $initialCount) {
1263
            throw new InvalidArgumentException(
1264
                'Argument 1 passed to ' .
1265
                $method .
1266
                ' must be an array containing any combination of ' .
1267
                implode(', ', $validThings)
1268
            );
1269
        }
1270
1271 3
        $this->NudgePropertyWithUniqueValues($property, $method, $value);
1272 3
    }
1273
}
1274