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.
Completed
Push — master ( 53bcfa...6873de )
by SignpostMarv
03:59
created

testProviderNonAbstractGoodFuzzingSetFromBlank()   F

Complexity

Conditions 13
Paths 343

Size

Total Lines 158
Code Lines 88

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 88
nc 343
nop 5
dl 0
loc 158
rs 3.7737
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftObject\Tests;
8
9
use Generator;
10
use ReflectionClass;
11
use ReflectionMethod;
12
use SignpostMarv\DaftObject;
13
14
class DaftObjectImplementationTest extends TestCase
15
{
16
    public function dataProviderImplementations() : Generator
17
    {
18
        foreach (
19
            [
20
                '/src/*.php' => 'SignpostMarv\\DaftObject\\',
21
                '/tests-src/*.php' => 'SignpostMarv\\DaftObject\\',
22
            ] as $glob => $ns
23
        ) {
24
            $files = glob(dirname(__DIR__) . $glob);
25
            foreach ($files as $file) {
26
                if (
27
                    is_file($file) &&
28
                    class_exists(
29
                        $className = (
30
                            $ns .
31
                            pathinfo($file, PATHINFO_FILENAME)
32
                        )
33
                    ) &&
34
                    is_a($className, DaftObject\DaftObject::class, true)
35
                ) {
36
                    yield [
37
                        $className,
38
                    ];
39
                }
40
            }
41
        }
42
    }
43
44
    final public function dataProviderInvalidImplementations() : array
45
    {
46
        $out = [];
47
48
        foreach ($this->InvalidImplementations() as $arg) {
49
            if (
50
                is_string($arg) &&
51
                class_exists($arg) &&
52
                is_a($arg, DaftObject\DaftObject::class, true)
53
            ) {
54
                $out[] = $arg;
55
            }
56
        }
57
58
        return $out;
59
    }
60
61
    final public function dataProviderNonAbstractImplementations() : Generator
62
    {
63
        foreach ($this->dataProviderImplementations() as [$className]) {
64
            if (
65
                is_string($className) &&
66
                is_a($className, DaftObject\DaftObject::class, true) &&
67
                false === (
68
                    (
69
                        $reflector = new ReflectionClass($className)
70
                    )->isAbstract()
71
                )
72
            ) {
73
                yield [
74
                    $className,
75
                    $reflector,
76
                ];
77
            }
78
        }
79
    }
80
81
    final public function dataProviderNonAbstractGoodImplementations() : Generator
82
    {
83
        $invalid = $this->dataProviderInvalidImplementations();
84
85
        foreach (
86
            $this->dataProviderNonAbstractImplementations() as [
87
                $className,
88
                $reflector,
89
            ]
90
        ) {
91
            if (false === in_array($className, $invalid, true)) {
92
                yield [
93
                    $className,
94
                    $reflector,
95
                ];
96
            }
97
        }
98
    }
99
100
    final public function dataProviderNonAbstractGoodImplementationsWithProperties() : Generator
101
    {
102
        foreach ($this->dataProviderNonAbstractGoodImplementations() as $args) {
103
            $className = $args[0];
104
105
            if (count($className::DaftObjectProperties()) > 0) {
106
                yield $args;
107
            }
108
        }
109
    }
110
111
    final public function dataProviderNonAbstractDefinesOwnIdGoodImplementations() : Generator
112
    {
113
        foreach ($this->dataProviderNonAbstractGoodImplementationsWithProperties() as $args) {
114
            $className = $args[0];
115
116
            if (is_a($className, DaftObject\DefinesOwnIdPropertiesInterface::class, true)) {
117
                yield $args;
118
            }
119
        }
120
    }
121
122
    final public function dataProviderNonAbstractGoodNullableImplementations() : Generator
123
    {
124
        foreach ($this->dataProviderNonAbstractGoodImplementationsWithProperties() as $args) {
125
            list($className) = $args;
126
127
            if (count($className::DaftObjectNullableProperties()) > 0) {
128
                yield $args;
129
            }
130
        }
131
    }
132
133
    final public function dataProviderNonAbstractGoodExportableImplementations() : Generator
134
    {
135
        foreach ($this->dataProviderNonAbstractGoodImplementations() as $args) {
136
            list($className) = $args;
137
138
            if (
139
                count($className::DaftObjectExportableProperties()) > 0 &&
140
                count($className::DaftObjectProperties()) > 0
141
            ) {
142
                yield $args;
143
            }
144
        }
145
    }
146
147
    final public function dataProviderNonAbstractGoodPropertiesImplementations() : Generator
148
    {
149
        foreach ($this->dataProviderNonAbstractGoodImplementations() as $args) {
150
            list($className) = $args;
151
152
            if (count($className::DaftObjectProperties()) > 0) {
153
                yield $args;
154
            }
155
        }
156
    }
157
158
    final public function dataProviderNonAbstractGetterSetters() : Generator
159
    {
160
        foreach (
161
            $this->dataProviderNonAbstractImplementations() as [
162
                $className,
163
                $reflector,
164
            ]
165
        ) {
166
            foreach (
167
                $reflector->getMethods() as $method
168
            ) {
169
                if (
170
                    preg_match('/^[GS]et[A-Z]/', $method->getName())
171
                ) {
172
                    yield [
173
                        $className,
174
                        $method,
175
                    ];
176
                }
177
            }
178
        }
179
    }
180
181
    final public function dataProviderGoodNonAbstractGetterSetters() : Generator
182
    {
183
        $invalid = $this->dataProviderInvalidImplementations();
184
185
        foreach (
186
            $this->dataProviderNonAbstractGetterSetters() as [
187
                $className,
188
                $method,
189
            ]
190
        ) {
191
            if (false === in_array($className, $invalid, true)) {
192
                yield [
193
                    $className,
194
                    $method,
195
                ];
196
            }
197
        }
198
    }
199
200
    final public function dataProviderFuzzingImplementations() : Generator
201
    {
202
        foreach ($this->FuzzingImplementationsViaGenerator() as $args) {
203
            if (
204
                is_array($args) &&
205
                2 === count($args) &&
206
                isset($args[0], $args[1]) &&
207
                is_string($args[0]) &&
208
                is_array($args[1]) &&
209
                is_a($args[0], DaftObject\DaftObject::class, true)
210
            ) {
211
                $validKeys = true;
212
                foreach (array_keys($args[1]) as $shouldBeProperty) {
213
                    if (false === is_string($shouldBeProperty)) {
214
                        $validKeys = false;
215
                        break;
216
                    }
217
                }
218
                if ($validKeys) {
219
                    yield [
220
                        $args[0],
221
                        $args[1],
222
                    ];
223
                }
224
            }
225
        }
226
    }
227
228
    final public function dataProviderNonAbstractGoodFuzzing() : Generator
229
    {
230
        foreach (
231
            $this->dataProviderNonAbstractGoodImplementations() as [
232
                $className,
233
                $reflector,
234
            ]
235
        ) {
236
            foreach (
237
                $this->dataProviderFuzzingImplementations() as [
238
                    $implementation,
239
                    $args,
240
                ]
241
            ) {
242
                if (is_a($className, $implementation, true)) {
243
                    /**
244
                    * @var DaftObject\DaftObject $className
245
                    */
246
                    $className = $className;
247
248
                    $getters = [];
249
                    $setters = [];
250
251
                    foreach (
252
                        $className::DaftObjectProperties() as $property
253
                    ) {
254
                        $propertyForMethod = ucfirst($property);
255
                        $getter = 'Get' . $propertyForMethod;
256
                        $setter = 'Set' . $propertyForMethod;
257
258
                        if ($reflector->hasMethod($getter)) {
259
                            /**
260
                            * @var ReflectionMethod
261
                            */
262
                            $getter = $reflector->getMethod($getter);
263
264
                            if ($getter->isPublic()) {
265
                                $getters[] = $property;
266
                            }
267
                        }
268
269
                        if ($reflector->hasMethod($setter)) {
270
                            /**
271
                            * @var ReflectionMethod
272
                            */
273
                            $setter = $reflector->getMethod($setter);
274
275
                            if ($setter->isPublic()) {
276
                                $setters[] = $property;
277
                            }
278
                        }
279
                    }
280
281
                    yield [
282
                        $className,
283
                        $reflector,
284
                        $args,
285
                        $getters,
286
                        $setters,
287
                    ];
288
                }
289
            }
290
        }
291
    }
292
293
    final public function dataProviderNonAbstractGoodFuzzingHasSetters(
294
    ) : Generator {
295
        foreach (
296
            $this->dataProviderNonAbstractGoodFuzzing() as [
297
                $className,
298
                $reflector,
299
                $args,
300
                $getters,
301
                $setters,
302
            ]
303
        ) {
304
            if (count($setters) > 0) {
305
                yield [
306
                    $className,
307
                    $reflector,
308
                    $args,
309
                    $getters,
310
                    $setters,
311
                ];
312
            }
313
        }
314
    }
315
316
    final public function dataProviderNonAbstractGoodFuzzingHasSettersPerProperty(
317
    ) : Generator {
318
        foreach (
319
            $this->dataProviderNonAbstractGoodFuzzingHasSetters() as [
320
                $className,
321
                $reflector,
322
                $args,
323
                $getters,
324
                $setters,
325
            ]
326
        ) {
327
            foreach ($setters as $property) {
328
                if (in_array($property, array_keys($args), true)) {
329
                    yield [
330
                        $className,
331
                        $reflector,
332
                        $args,
333
                        $getters,
334
                        $setters,
335
                        $property,
336
                    ];
337
                }
338
            }
339
        }
340
    }
341
342
    final public function dataProviderNonAbstractGoodFuzzingHasSettersPerPropertyWorm(
343
    ) : Generator {
344
        foreach (
345
            $this->dataProviderNonAbstractGoodFuzzingHasSettersPerProperty() as [
346
                $className,
347
                $reflector,
348
                $args,
349
                $getters,
350
                $setters,
351
                $property,
352
            ]
353
        ) {
354
            if (is_a($className, DaftObject\DaftObjectWorm::class, true)) {
355
                yield [
356
                    $className,
357
                    $reflector,
358
                    $args,
359
                    $getters,
360
                    $setters,
361
                    $property,
362
                ];
363
            }
364
        }
365
    }
366
367
    final public function dataProviderNonAbstractGoodFuzzingHasSettersPerPropertyNotNullable(
368
    ) : Generator {
369
        foreach (
370
            $this->dataProviderNonAbstractGoodFuzzingHasSettersPerProperty() as [
371
                $className,
372
                $reflector,
373
                $args,
374
                $getters,
375
                $setters,
376
                $property,
377
            ]
378
        ) {
379
            if (
380
                false === in_array(
381
                    $property,
382
                    $className::DaftObjectNullableProperties(),
383
                    true
384
                )
385
            ) {
386
                yield [
387
                    $className,
388
                    $reflector,
389
                    $args,
390
                    $getters,
391
                    $setters,
392
                    $property,
393
                ];
394
            }
395
        }
396
    }
397
398
    /**
399
    * @dataProvider dataProviderNonAbstractGoodImplementationsWithProperties
400
    */
401
    final public function testHasDefinedAllPropertiesCorrectly(
402
        string $className,
403
        ReflectionClass $reflector
404
    ) : void {
405
        $properties = $className::DaftObjectProperties();
406
407
        $this->assertGreaterThan(0, count($properties));
408
409
        foreach ($properties as $property) {
410
            $this->assertInternalType(
411
                'string',
412
                $property,
413
                (
414
                    $className .
415
                    '::DaftObjectProperties()' .
416
                    ' must return an array of strings'
417
                )
418
            );
419
        }
420
    }
421
422
    /**
423
    * @dataProvider dataProviderNonAbstractDefinesOwnIdGoodImplementations
424
    */
425
    final public function testHasDefinedAllIdPropertiesCorrectly(
426
        string $className,
427
        ReflectionClass $reflector
428
    ) : void {
429
        $interfaceCheck = $className;
430
431
        $this->assertTrue(
432
            is_a(
433
                $interfaceCheck,
434
                DaftObject\DefinesOwnIdPropertiesInterface::class,
435
                true
436
            )
437
        );
438
439
        $properties = $className::DaftObjectProperties();
440
441
        $this->assertGreaterThan(0, count($properties));
442
443
        foreach ($className::DaftObjectIdProperties() as $property) {
444
            $this->assertInternalType(
445
                'string',
446
                $property,
447
                (
448
                    $className .
449
                    '::DaftObjectIdProperties()' .
450
                    ' must return an array of strings'
451
                )
452
            );
453
            $this->assertTrue(
454
                in_array($property, $properties, true),
455
                (
456
                    $className .
457
                    '::DaftObjectIdProperties() defines as property (' .
458
                    $property .
459
                    ') that is not defined on ' .
460
                    $className .
461
                    '::DaftObjectProperties()'
462
                )
463
            );
464
        }
465
    }
466
467
    /**
468
    * @dataProvider dataProviderNonAbstractGoodNullableImplementations
469
    *
470
    * @depends testHasDefinedAllPropertiesCorrectly
471
    */
472
    final public function testHasDefinedAllNullablesCorrectly(
473
        string $className,
474
        ReflectionClass $reflector
475
    ) : void {
476
        $nullables = $className::DaftObjectNullableProperties();
477
478
        foreach ($nullables as $nullable) {
479
            $this->assertInternalType(
480
                'string',
481
                $nullable,
482
                (
483
                    $className .
484
                    '::DaftObjectNullableProperties()' .
485
                    ' must return an array of strings'
486
                )
487
            );
488
        }
489
490
        $properties = $className::DaftObjectProperties();
491
492
        foreach ($nullables as $nullable) {
493
            $this->assertTrue(
494
                in_array($nullable, $properties, true),
495
                (
496
                    $className .
497
                    '::DaftObjectNullableProperties()' .
498
                    ' ' .
499
                    'a nullable property (' .
500
                    $nullable .
501
                    ') that was not defined as a property on ' .
502
                    $className .
503
                    '::DaftObjectProperties()'
504
                )
505
            );
506
        }
507
508
        if (count($properties) > 0 && 0 === count($nullables)) {
509
            foreach ($properties as $property) {
510
                $getter = 'Get' . $property;
511
                $setter = 'Set' . $property;
512
513
                if ($reflector->hasMethod($getter)) {
514
                    $method = $reflector->getMethod($getter);
515
516
                    $this->assertTrue(
517
                        $method->hasReturnType(),
518
                        (
519
                            $method->getDeclaringClass()->getName() .
520
                            '::' .
521
                            $getter .
522
                            ' had no return type, cannot verify is not nullable.'
523
                        )
524
                    );
525
526
                    /**
527
                    * @var \ReflectionType $returnType
528
                    */
529
                    $returnType = $method->getReturnType();
530
531
                    $this->assertFalse(
532
                        $returnType->allowsNull(),
533
                        (
534
                            $method->getDeclaringClass()->getName() .
535
                            '::' .
536
                            $getter .
537
                            ' defines a nullable return type, but ' .
538
                            $className .
539
                            ' indicates no nullable properties!'
540
                        )
541
                    );
542
                }
543
                if ($reflector->hasMethod($setter)) {
544
                    $method = $reflector->getMethod($setter);
545
546
                    $this->assertGreaterThan(
547
                        0,
548
                        $method->getNumberOfParameters(),
549
                        (
550
                            $method->getDeclaringClass()->getName() .
551
                            '::' .
552
                            $setter .
553
                            ' has no parameters, cannot verify is not nullable!'
554
                        )
555
                    );
556
557
                    foreach ($method->getParameters() as $param) {
558
                        $this->assertFalse(
559
                            $param->allowsNull(),
560
                            (
561
                                $method->getDeclaringClass()->getName() .
562
                                '::' .
563
                                $setter .
564
                                ' defines a parameter that allows null, but ' .
565
                                $className .
566
                                ' indicates no nullable properties!'
567
                            )
568
                        );
569
                    }
570
                }
571
            }
572
        }
573
    }
574
575
    /**
576
    * @dataProvider dataProviderNonAbstractGoodExportableImplementations
577
    *
578
    * @depends testHasDefinedAllPropertiesCorrectly
579
    */
580
    final public function testHasDefinedAllExportablesCorrectly(
581
        string $className,
582
        ReflectionClass $reflector
583
    ) : void {
584
        $exportables = $className::DaftObjectExportableProperties();
585
586
        foreach ($exportables as $exportable) {
587
            $this->assertInternalType(
588
                'string',
589
                $exportable,
590
                (
591
                    $className .
592
                    '::DaftObjectExportableProperties()' .
593
                    ' must return an array of strings'
594
                )
595
            );
596
        }
597
598
        $properties = $className::DaftObjectProperties();
599
600
        foreach ($exportables as $exportable) {
601
            $this->assertTrue(
602
                in_array($exportable, $properties, true),
603
                (
604
                    $className .
605
                    '::DaftObjectNullableProperties()' .
606
                    ' ' .
607
                    'a nullable property (' .
608
                    $exportable .
609
                    ') that was not defined as a property on ' .
610
                    $className .
611
                    '::DaftObjectProperties()'
612
                )
613
            );
614
        }
615
616
        if (0 === count($exportables) && count($properties) > 0) {
617
            $this->assertFalse(
618
                is_a($className, DaftObject\DaftJson::class, true),
619
                (
620
                    'Implementations with no exportables should not implement ' .
621
                    DaftObject\DaftJson::class
622
                )
623
            );
624
        }
625
    }
626
627
    /**
628
    * @dataProvider dataProviderNonAbstractGoodPropertiesImplementations
629
    *
630
    * @depends testHasDefinedAllNullablesCorrectly
631
    * @depends testHasDefinedAllExportablesCorrectly
632
    */
633
    final public function testHasDefinedImplementationCorrectly(
634
        string $className,
635
        ReflectionClass $reflector
636
    ) : void {
637
        $properties = $className::DaftObjectProperties();
638
639
        $nullables = $className::DaftObjectNullableProperties();
640
641
        $exportables = $className::DaftObjectExportableProperties();
0 ignored issues
show
Unused Code introduced by
The assignment to $exportables is dead and can be removed.
Loading history...
642
643
        /*
644
        * @var ReflectionClass $reflector
645
        */
646
647
        foreach ($properties as $property) {
648
            $getter = 'Get' . ucfirst($property);
649
            $setter = 'Set' . ucfirst($property);
650
651
            $hasAny = (
652
                $reflector->hasMethod($getter) ||
653
                $reflector->hasMethod($setter)
654
            );
655
656
            $this->assertTrue(
657
                $hasAny,
658
                (
659
                    $className .
660
                    ' must implement at least a getter or setter for ' .
661
                    $className .
662
                    '::$' .
663
                    $property
664
                )
665
            );
666
667
            if (false === $hasAny) {
668
                continue;
669
            }
670
671
            $reflectorGetter = null;
672
            $getterPublic = (
673
                $reflector->hasMethod($getter) &&
674
                ($reflectorGetter = $reflector->getMethod($getter))->isPublic()
675
            );
676
677
            $reflectorSetter = null;
678
            $setterPublic = (
679
                $reflector->hasMethod($setter) &&
680
                ($reflectorSetter = $reflector->getMethod($setter))->isPublic()
681
            );
682
683
            $anyPublic = $getterPublic || $setterPublic;
684
685
            $isNullable = in_array($property, $nullables, true);
686
687
            $this->assertTrue(
688
                $anyPublic,
689
                (
690
                    $className .
691
                    ' must implement at least a public getter or setter for ' .
692
                    $className .
693
                    '::$' .
694
                    $property
695
                )
696
            );
697
698
            if ($getterPublic) {
699
                /**
700
                * @var ReflectionMethod $reflectorGetter
701
                */
702
                $reflectorGetter = $reflectorGetter;
703
704
                $this->assertSame(
705
                    0,
706
                    $reflectorGetter->getNumberOfParameters(),
707
                    (
708
                        $reflectorGetter->getDeclaringClass()->getName() .
709
                        '::' .
710
                        $reflectorGetter->getName() .
711
                        '() must not have any parameters.'
712
                    )
713
                );
714
                $this->assertTrue(
715
                    $reflectorGetter->hasReturnType(),
716
                    (
717
                        $reflectorGetter->getNumberOfParameters() .
718
                        $reflectorGetter->getDeclaringClass()->getName() .
719
                        '::' .
720
                        $reflectorGetter->getName() .
721
                        '() must have a return type.'
722
                    )
723
                );
724
725
                $returnType = null;
726
727
                if ($reflectorGetter->hasReturnType()) {
728
                    /**
729
                    * @var \ReflectionType $returnType
730
                    */
731
                    $returnType = $reflectorGetter->getReturnType();
732
733
                    $this->assertTrue(
734
                        (
735
                            $reflectorGetter->hasReturnType() &&
736
                            'void' !== $returnType->__toString()
0 ignored issues
show
Deprecated Code introduced by
The function ReflectionType::__toString() has been deprecated: 7.1.0:8.0.0 Please use getName() ( Ignorable by Annotation )

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

736
                            'void' !== /** @scrutinizer ignore-deprecated */ $returnType->__toString()

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
737
                        ),
738
                        (
739
                            $reflectorGetter->getNumberOfParameters() .
740
                            $reflectorGetter->getDeclaringClass()->getName() .
741
                            '::' .
742
                            $reflectorGetter->getName() .
743
                            '() must have a non-void return type.'
744
                        )
745
                    );
746
747
                    if ($isNullable) {
748
                        $this->assertTrue(
749
                            (
750
                                $reflectorGetter->hasReturnType() &&
751
                                $returnType->allowsNull()
752
                            ),
753
                            (
754
                                $reflectorGetter->getNumberOfParameters() .
755
                                $reflectorGetter->getDeclaringClass()->getName() .
756
                                '::' .
757
                                $reflectorGetter->getName() .
758
                                '() must have a nullable return type.'
759
                            )
760
                        );
761
                    }
762
                }
763
            }
764
765
            if ($setterPublic) {
766
                /**
767
                * @var ReflectionMethod $reflectorSetter
768
                */
769
                $reflectorSetter = $reflectorSetter;
770
771
                $this->assertSame(
772
                    1,
773
                    $reflectorSetter->getNumberOfParameters(),
774
                    (
775
                        $reflectorSetter->getDeclaringClass()->getName() .
776
                        '::' .
777
                        $reflectorSetter->getName() .
778
                        '() must have only one parameter.'
779
                    )
780
                );
781
782
                $this->assertTrue(
783
                    $reflectorSetter->hasReturnType(),
784
                    (
785
                        $reflectorSetter->getNumberOfParameters() .
786
                        $reflectorSetter->getDeclaringClass()->getName() .
787
                        '::' .
788
                        $reflectorSetter->getName() .
789
                        '() must specify a void return type.'
790
                    )
791
                );
792
793
                if ($reflectorSetter->hasReturnType()) {
794
                    /**
795
                    * @var \ReflectionType $returnType
796
                    */
797
                    $returnType = $reflectorSetter->getReturnType();
798
799
                    $this->assertSame(
800
                        'void',
801
                        $returnType->__toString(),
0 ignored issues
show
Deprecated Code introduced by
The function ReflectionType::__toString() has been deprecated: 7.1.0:8.0.0 Please use getName() ( Ignorable by Annotation )

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

801
                        /** @scrutinizer ignore-deprecated */ $returnType->__toString(),

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
802
                        (
803
                            $reflectorSetter->getDeclaringClass()->getName() .
804
                            '::' .
805
                            $reflectorSetter->getName() .
806
                            '() must specify a void return type, "' .
807
                            $returnType->__toString() .
0 ignored issues
show
Deprecated Code introduced by
The function ReflectionType::__toString() has been deprecated: 7.1.0:8.0.0 Please use getName() ( Ignorable by Annotation )

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

807
                            /** @scrutinizer ignore-deprecated */ $returnType->__toString() .

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
808
                            '" found.'
809
                        )
810
                    );
811
                }
812
813
                if (
814
                    $reflectorSetter->getParameters()[0]->hasType()
815
                ) {
816
                    $this->assertSame(
817
                        (
818
                            $reflectorSetter->getParameters()[0]
819
                        )->getType()->allowsNull(),
820
                        $isNullable,
821
                        (
822
                            $reflectorSetter->getDeclaringClass()->getName() .
823
                            '::' .
824
                            $reflectorSetter->getName() .
825
                            '() must have a ' .
826
                            (
827
                                $isNullable
828
                                    ? ''
829
                                    : 'non-'
830
                            ) .
831
                            'nullable type when specified.'
832
                        )
833
                    );
834
                }
835
            }
836
        }
837
    }
838
839
    /**
840
    * @dataProvider dataProviderGoodNonAbstractGetterSetters
841
    *
842
    * @depends testHasDefinedImplementationCorrectly
843
    */
844
    final public function testHasAllGettersAndSettersDefinedAsProperties(
845
        string $className,
846
        ReflectionMethod $reflector
847
    ) : void {
848
        $property = mb_substr($reflector->getName(), 3);
849
850
        $properties = $className::DaftObjectProperties();
851
852
        $defined = (
853
            in_array($property, $properties, true) ||
854
            in_array(
855
                lcfirst($property),
856
                $properties,
857
                true
858
            )
859
        );
860
861
        $definesOwnId = is_a(
862
            $className,
863
            DaftObject\DefinesOwnIdPropertiesInterface::class,
864
            true
865
        );
866
867
        if (
868
            false === $defined &&
869
            $definesOwnId
870
        ) {
871
            $this->markTestSkipped(
872
                $reflector->getDeclaringClass()->getName() .
873
                '::' .
874
                $reflector->getName() .
875
                '() is facilitated by ' .
876
                DaftObject\DefinesOwnIdPropertiesInterface::class
877
            );
878
        } else {
879
            $this->assertTrue(
880
                $defined,
881
                (
882
                    $reflector->getDeclaringClass()->getName() .
883
                    '::' .
884
                    $reflector->getName() .
885
                    '() was not defined in ' .
886
                    $className .
887
                    '::DaftObjectProperties()'
888
                )
889
            );
890
        }
891
    }
892
893
    /**
894
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSetters
895
    *
896
    * @depends testHasDefinedImplementationCorrectly
897
    *
898
    * @psalm-suppress ForbiddenCode
899
    */
900
    final public function testProviderNonAbstractGoodFuzzingSetFromBlank(
901
        string $className,
902
        ReflectionClass $reflector,
903
        array $args,
904
        array $getters,
905
        array $setters
906
    ) : void {
907
        $interfaceCheck = $className;
908
909
        if (is_a($interfaceCheck, DaftObject\DaftObjectWorm::class, true)) {
910
            $this->markTestSkipped(
911
                $className .
912
                ' is an implementation of ' .
913
                DaftObject\DaftObjectWorm::class .
914
                ', cannot test for instantiation from blank.'
915
            );
916
917
            return;
918
        }
919
920
        $obj = new $className($args);
921
922
        $this->assertSame(
923
            0,
924
            count($obj->ChangedProperties()),
925
            (
926
                $className .
927
                '::ChangedProperties() must be empty after instantiation'
928
            )
929
        );
930
931
        $obj = new $className([]);
932
933
        $this->assertSame(
934
            0,
935
            count($obj->ChangedProperties()),
936
            (
937
                $className .
938
                '::ChangedProperties() must be empty after instantiation'
939
            )
940
        );
941
942
        $settersNotNull = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $settersNotNull is dead and can be removed.
Loading history...
943
944
        foreach ($setters as $property) {
945
            $this->assertFalse(
946
                $obj->HasPropertyChanged($property),
947
                (
948
                    $className .
949
                    '::$' .
950
                    $property .
951
                    ' should not be marked as changed' .
952
                    ' when instantiating from blank.'
953
                )
954
            );
955
956
            if (isset($args[$property])) {
957
                $obj->$property = $args[$property];
958
959
                $this->assertTrue(
960
                    $obj->HasPropertyChanged($property),
961
                    (
962
                        $className .
963
                        '::$' .
964
                        $property .
965
                        ' should be marked as changed.'
966
                    )
967
                );
968
969
                $obj->MakePropertiesUnchanged($property);
970
971
                $this->assertFalse(
972
                    $obj->HasPropertyChanged($property),
973
                    (
974
                        $className .
975
                        '::$' .
976
                        $property .
977
                        ' should be marked as unchanged after calling ' .
978
                        $className .
979
                        '::MakePropertiesUnchanged()'
980
                    )
981
                );
982
            }
983
        }
984
985
        /**
986
        * @var DaftObject\DaftObject $obj
987
        */
988
        $obj = new $className([]);
989
990
        foreach ($setters as $property) {
991
            $obj->$property = $args[$property];
992
993
            if (in_array($property, $getters, true)) {
994
                $this->assertSame(
995
                    $args[$property],
996
                    $obj->$property
997
                );
998
            }
999
        }
1000
1001
        ob_start();
1002
        var_dump($obj);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($obj) looks like debug code. Are you sure you do not want to remove it?
Loading history...
1003
1004
        $debugInfo = ob_get_clean();
1005
1006
        $regex = '/' . static::RegexForObject($obj) . '$/s';
1007
1008
        $this->assertRegExp(
1009
            $regex,
1010
            str_replace(["\n"], ' ', (string) $debugInfo)
1011
        );
1012
1013
        foreach ($setters as $property) {
1014
            $this->assertTrue(
1015
                in_array($property, $obj->ChangedProperties(), true),
1016
                (
1017
                    $className .
1018
                    '::ChangedProperties() must contain changed properties'
1019
                )
1020
            );
1021
        }
1022
1023
        foreach ($className::DaftObjectNullableProperties() as $property) {
1024
            $checkGetterIsNull = (
1025
                in_array($property, $getters, true) &&
1026
                isset($args[$property]) &&
1027
                false === is_null($args[$property])
1028
            );
1029
1030
            if ($obj->HasPropertyChanged($property)) {
1031
                if ($checkGetterIsNull) {
1032
                    $this->assertTrue(
1033
                        isset($obj->$property),
1034
                        (
1035
                            $className .
1036
                            '::__isset(' .
1037
                            $property .
1038
                            ') must return true after ' .
1039
                            $className .
1040
                            '::$' .
1041
                            $property .
1042
                            ' has been set'
1043
                        )
1044
                    );
1045
                }
1046
1047
                unset($obj->$property);
1048
            }
1049
1050
            if ($checkGetterIsNull) {
1051
                $this->assertNull(
1052
                    $obj->$property,
1053
                    (
1054
                        $className .
1055
                        '::$' .
1056
                        $property .
1057
                        ' must be null after being unset'
1058
                    )
1059
                );
1060
            }
1061
        }
1062
    }
1063
1064
    /**
1065
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSetters
1066
    *
1067
    * @depends testHasDefinedImplementationCorrectly
1068
    */
1069
    final public function testProviderNonAbstractGoodFuzzingSetFromBlankThenJsonSerialiseMaybeFailure(
1070
        string $className,
1071
        ReflectionClass $reflector,
1072
        array $args,
1073
        array $getters,
1074
        array $setters
1075
    ) : void {
1076
        $obj = new $className($args);
1077
1078
        if (
1079
            ($obj instanceof DaftObject\DaftJson)
1080
        ) {
1081
            $obj->jsonSerialize();
1082
1083
            $json = json_encode($obj);
1084
1085
            $this->assertInternalType(
1086
                'string',
1087
                $json,
1088
                (
1089
                    'Instances of ' .
1090
                    $className .
1091
                    ' should resolve to a string when passed to json_encode()'
1092
                )
1093
            );
1094
1095
            $decoded = json_decode((string) $json, true);
1096
1097
            $this->assertInternalType(
1098
                'array',
1099
                $decoded,
1100
                (
1101
                    'JSON-encoded implementations of ' .
1102
                    DaftObject\DaftJson::class .
1103
                    ' (' .
1104
                    $className .
1105
                    ')' .
1106
                    ' must decode to an array!'
1107
                )
1108
            );
1109
1110
            $objFromJson = $className::DaftObjectFromJsonArray($decoded);
1111
1112
            $this->assertSame(
1113
                $json,
1114
                json_encode($objFromJson),
1115
                (
1116
                    'JSON-encoded implementations of ' .
1117
                    DaftObject\DaftJson::class .
1118
                    ' must encode($obj) the same as encode(decode($str))'
1119
                )
1120
            );
1121
1122
            $objFromJson = $className::DaftObjectFromJsonString($json);
1123
1124
            $this->assertSame(
1125
                $json,
1126
                json_encode($objFromJson),
1127
                (
1128
                    'JSON-encoded implementations of ' .
1129
                    DaftObject\DaftJson::class .
1130
                    ' must encode($obj) the same as encode(decode($str))'
1131
                )
1132
            );
1133
        } else {
1134
            if (method_exists($obj, 'jsonSerialize')) {
1135
                $this->expectException(DaftObject\DaftObjectNotDaftJsonBadMethodCallException::class);
1136
                $this->expectExceptionMessage(
1137
                    sprintf(
1138
                        '%s does not implement %s',
1139
                        $className,
1140
                        DaftObject\DaftJson::class
1141
                    )
1142
                );
1143
1144
                $obj->jsonSerialize();
1145
1146
                return;
1147
            }
1148
            $this->markTestSkipped(
1149
                sprintf(
1150
                    '%s does not implement %s or %s::jsonSerialize()',
1151
                    $className,
1152
                    DaftObject\DaftJson::class,
1153
                    $className
1154
                )
1155
            );
1156
1157
            return;
1158
        }
1159
    }
1160
1161
    /**
1162
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSetters
1163
    *
1164
    * @depends testHasDefinedImplementationCorrectly
1165
    *
1166
    * @psalm-suppress TypeDoesNotContainType
1167
    */
1168
    final public function testProviderNonAbstractGoodFuzzingJsonFromArrayFailure(
1169
        string $className,
1170
        ReflectionClass $reflector,
1171
        array $args,
1172
        array $getters,
1173
        array $setters
1174
    ) : void {
1175
        if (
1176
            false === is_a($className, DaftObject\DaftJson::class, true) &&
1177
            is_a(
1178
                $className,
1179
                DaftObject\AbstractArrayBackedDaftObject::class,
1180
                true
1181
            )
1182
        ) {
1183
            $this->expectException(DaftObject\DaftObjectNotDaftJsonBadMethodCallException::class);
1184
            $this->expectExceptionMessage(
1185
                sprintf(
1186
                    '%s does not implement %s',
1187
                    $className,
1188
                    DaftObject\DaftJson::class
1189
                )
1190
            );
1191
1192
            /**
1193
            * @var DaftObject\DaftJson $className
1194
            */
1195
            $className = $className;
1196
1197
            $className::DaftObjectFromJsonArray([]);
1198
        } else {
1199
            $this->markTestSkipped(
1200
                sprintf(
1201
                    '%s is not an implementation of %s or %s',
1202
                    $className,
1203
                    DaftObject\DaftJson::class,
1204
                    DaftObject\AbstractArrayBackedDaftObject::class
1205
                )
1206
            );
1207
        }
1208
    }
1209
1210
    /**
1211
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSetters
1212
    *
1213
    * @depends testHasDefinedImplementationCorrectly
1214
    *
1215
    * @psalm-suppress TypeDoesNotContainType
1216
    */
1217
    final public function testProviderNonAbstractGoodFuzzingJsonFromStringFailure(
1218
        string $className,
1219
        ReflectionClass $reflector,
1220
        array $args,
1221
        array $getters,
1222
        array $setters
1223
    ) : void {
1224
        if (
1225
            false === is_a($className, DaftObject\DaftJson::class, true) &&
1226
            is_a(
1227
                $className,
1228
                DaftObject\AbstractArrayBackedDaftObject::class,
1229
                true
1230
            )
1231
        ) {
1232
            $this->expectException(DaftObject\DaftObjectNotDaftJsonBadMethodCallException::class);
1233
            $this->expectExceptionMessage(
1234
                sprintf(
1235
                    '%s does not implement %s',
1236
                    $className,
1237
                    DaftObject\DaftJson::class
1238
                )
1239
            );
1240
1241
            /**
1242
            * @var DaftObject\DaftJson $className
1243
            */
1244
            $className = $className;
1245
1246
            $className::DaftObjectFromJsonString('{}');
1247
        } else {
1248
            $this->markTestSkipped(
1249
                sprintf(
1250
                    '%s is not an implementation of %s or %s',
1251
                    $className,
1252
                    DaftObject\DaftJson::class,
1253
                    DaftObject\AbstractArrayBackedDaftObject::class
1254
                )
1255
            );
1256
        }
1257
    }
1258
1259
    /**
1260
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSetters
1261
    *
1262
    * @depends testHasDefinedAllExportablesCorrectly
1263
    * @depends testHasDefinedImplementationCorrectly
1264
    */
1265
    final public function testProviderNonAbstractGoodFuzzingSetFromBlankThenJsonSerialiseMaybePropertiesFailure(
1266
        string $className,
1267
        ReflectionClass $reflector,
1268
        array $args,
1269
        array $getters,
1270
        array $setters
1271
    ) : void {
1272
        /**
1273
        * @var DaftObject\DaftObject $className
1274
        */
1275
        $className = $className;
1276
1277
        if (is_a($className, DaftObject\DaftJson::class, true)) {
1278
            /**
1279
            * @var DaftObject\DaftJson $className
1280
            */
1281
            $className = $className;
1282
1283
            $exportables = $className::DaftObjectExportableProperties();
1284
1285
            $propertyNames = $className::DaftObjectJsonPropertyNames();
1286
1287
            $jsonProps = [];
1288
1289
            foreach ($className::DaftObjectJsonProperties() as $k => $v) {
1290
                $prop = $v;
1291
1292
                if (is_string($k)) {
1293
                    $this->assertInternalType(
1294
                        'string',
1295
                        $v,
1296
                        sprintf(
1297
                            (
1298
                                '%s::DaftObjectJsonProperties()' .
1299
                                ' ' .
1300
                                'key-value pairs' .
1301
                                ' ' .
1302
                                'must be either array<int, string>' .
1303
                                ' or ' .
1304
                                'array<string, string>'
1305
                            ),
1306
                            $className
0 ignored issues
show
Bug introduced by
$className of type SignpostMarv\DaftObject\DaftJson is incompatible with the type string expected by parameter $args of sprintf(). ( Ignorable by Annotation )

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

1306
                            /** @scrutinizer ignore-type */ $className
Loading history...
1307
                        )
1308
                    );
1309
1310
                    if ('[]' === mb_substr($v, -2)) {
1311
                        $v = mb_substr($v, 0, -2);
1312
                    }
1313
1314
                    $this->assertTrue(
1315
                        class_exists($v),
1316
                        sprintf(
1317
                            (
1318
                                'When %s::DaftObjectJsonProperties()' .
1319
                                ' ' .
1320
                                'key-value pair is array<string, string>' .
1321
                                ' ' .
1322
                                'the value must refer to a class.'
1323
                            ),
1324
                            $className
1325
                        )
1326
                    );
1327
1328
                    $this->assertTrue(
1329
                        is_a($v, DaftObject\DaftJson::class, true),
1330
                        sprintf(
1331
                            (
1332
                                'When %s::DaftObjectJsonProperties()' .
1333
                                ' ' .
1334
                                'key-value pair is array<string, string>' .
1335
                                ' ' .
1336
                                'the value must be an implementation of %s'
1337
                            ),
1338
                            $className,
1339
                            DaftObject\DaftJson::class
1340
                        )
1341
                    );
1342
1343
                    $prop = $k;
1344
                }
1345
1346
                $this->assertContains(
1347
                    $prop,
1348
                    $exportables,
1349
                    sprintf(
1350
                        (
1351
                            'Properties listed in' .
1352
                            ' ' .
1353
                            '%s::DaftObjectJsonProperties() must also be' .
1354
                            ' ' .
1355
                            'listed in %s::DaftObjectExportableProperties()'
1356
                        ),
1357
                        $className,
1358
                        $className
1359
                    )
1360
                );
1361
1362
                $this->assertContains(
1363
                    $prop,
1364
                    $propertyNames,
1365
                    sprintf(
1366
                        (
1367
                            'Properties listed in' .
1368
                            ' ' .
1369
                            '%s::DaftObjectJsonProperties() must also be' .
1370
                            ' ' .
1371
                            'listed in %s::DaftObjectJsonPropertyNames()'
1372
                        ),
1373
                        $className,
1374
                        $className
1375
                    )
1376
                );
1377
1378
                $jsonProps[] = $prop;
1379
            }
1380
1381
            foreach ($propertyNames as $prop) {
1382
                $this->assertContains(
1383
                    $prop,
1384
                    $propertyNames,
1385
                    sprintf(
1386
                        (
1387
                            'Properties listed in' .
1388
                            ' ' .
1389
                            '%s::DaftObjectJsonPropertyNames() must also be' .
1390
                            ' ' .
1391
                            'listed or referenced in' .
1392
                            ' ' .
1393
                            '%s::DaftObjectJsonProperties()'
1394
                        ),
1395
                        $className,
1396
                        $className
1397
                    )
1398
                );
1399
            }
1400
        } elseif (
1401
            is_a(
1402
                $className,
1403
                DaftObject\AbstractArrayBackedDaftObject::class,
1404
                true
1405
            )
1406
        ) {
1407
            $this->expectException(DaftObject\DaftObjectNotDaftJsonBadMethodCallException::class);
1408
            $this->expectExceptionMessage(
1409
                sprintf(
1410
                    '%s does not implement %s',
1411
                    $className,
0 ignored issues
show
Bug introduced by
$className of type SignpostMarv\DaftObject\DaftObject is incompatible with the type string expected by parameter $args of sprintf(). ( Ignorable by Annotation )

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

1411
                    /** @scrutinizer ignore-type */ $className,
Loading history...
1412
                    DaftObject\DaftJson::class
1413
                )
1414
            );
1415
1416
            /**
1417
            * @var DaftObject\DaftJson $className
1418
            */
1419
            $className = $className;
1420
1421
            $className::DaftObjectJsonProperties();
1422
        }
1423
    }
1424
1425
    /**
1426
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSettersPerPropertyWorm
1427
    *
1428
    * @depends testHasDefinedImplementationCorrectly
1429
    */
1430
    final public function testProviderNonAbstractGoodFuzzingHasSettersPerPropertyWorm(
1431
        string $className,
1432
        ReflectionClass $reflector,
1433
        array $args,
1434
        array $getters,
1435
        array $setters,
1436
        string $property
1437
    ) : void {
1438
        $obj = new $className($args, true);
1439
1440
        $this->expectException(
1441
            DaftObject\PropertyNotRewriteableException::class
1442
        );
1443
        $this->expectExceptionMessage(
1444
            sprintf(
1445
                'Property not rewriteable: ' .
1446
                $className .
1447
                '::$' .
1448
                $property
1449
            )
1450
        );
1451
1452
        $obj->$property = $args[$property];
1453
    }
1454
1455
    /**
1456
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSettersPerPropertyWorm
1457
    *
1458
    * @depends testHasDefinedImplementationCorrectly
1459
    */
1460
    final public function testProviderNonAbstractGoodFuzzingHasSettersPerPropertyWormAfterCreate(
1461
        string $className,
1462
        ReflectionClass $reflector,
1463
        array $args,
1464
        array $getters,
1465
        array $setters,
1466
        string $property
1467
    ) : void {
1468
        $obj = new $className([], true);
1469
1470
        $obj->$property = $args[$property];
1471
1472
        $this->expectException(
1473
            DaftObject\PropertyNotRewriteableException::class
1474
        );
1475
        $this->expectExceptionMessage(
1476
            sprintf(
1477
                'Property not rewriteable: ' .
1478
                $className .
1479
                '::$' .
1480
                $property
1481
            )
1482
        );
1483
1484
        $obj->$property = $args[$property];
1485
    }
1486
1487
    /**
1488
    * @dataProvider dataProviderNonAbstractGoodFuzzingHasSettersPerPropertyNotNullable
1489
    *
1490
    * @psalm-suppress TypeDoesNotContainType
1491
    */
1492
    final public function testNonAbstractGoodFuzzingHasSettersPerPropertyNotNullable(
1493
        string $className,
1494
        ReflectionClass $reflector,
1495
        array $args,
1496
        array $getters,
1497
        array $setters,
1498
        string $property
1499
    ) : void {
1500
        if (
1501
            is_a($className, DaftObject\AbstractDaftObject::class, true) &&
1502
            in_array($property, $setters, true)
1503
        ) {
1504
            /**
1505
            * @var ReflectionMethod $method
1506
            */
1507
            $method = $reflector->getMethod('NudgePropertyValue');
1508
1509
            $method->setAccessible(true);
1510
1511
            $this->expectException(
1512
                DaftObject\PropertyNotNullableException::class
1513
            );
1514
            $this->expectExceptionMessage(
1515
                sprintf(
1516
                    'Property not nullable: %s::$%s',
1517
                    $className,
1518
                    $property
1519
                )
1520
            );
1521
1522
            $method->invoke(new $className(), $property, null);
1523
        }
1524
    }
1525
1526
    protected static function RegexForObject(DaftObject\DaftObject $obj) : string
1527
    {
1528
        $props = [];
1529
1530
        foreach ($obj::DaftObjectExportableProperties() as $prop) {
1531
            $expectedMethod = 'Get' . ucfirst($prop);
1532
            if (
1533
                $obj->__isset($prop) &&
1534
                method_exists($obj, $expectedMethod) &&
1535
                (
1536
                    new ReflectionMethod($obj, $expectedMethod)
1537
                )->isPublic()
1538
            ) {
1539
                $props[$prop] = $obj->$expectedMethod();
1540
            }
1541
        }
1542
1543
        return static::RegexForArray(get_class($obj), $props);
1544
    }
1545
1546
    protected static function RegexForArray(string $className, array $props) : string
1547
    {
1548
        $regex =
1549
            '(?:class |object\()' .
1550
            preg_quote($className, '/') .
1551
            '[\)]{0,1}#' .
1552
            '\d+ \(' .
1553
            preg_quote((string) count($props), '/') .
1554
            '\) \{.+';
1555
1556
        foreach ($props as $prop => $val) {
1557
            $regex .=
1558
                ' (?:public ' .
1559
                preg_quote('$' . $prop, '/') .
1560
                '|' .
1561
                preg_quote('["' . $prop . '"]', '/') .
1562
                ')[ ]{0,1}' .
1563
                preg_quote('=', '/') .
1564
                '>.+' .
1565
                static::RegexForVal($val) .
1566
                '.+';
1567
        }
1568
1569
        $regex .= '.+';
1570
1571
        return $regex;
1572
    }
1573
1574
    /**
1575
    * @param mixed $val
1576
    */
1577
    protected static function RegexForVal($val) : string
1578
    {
1579
        if (is_array($val)) {
1580
            $out = '(?:';
1581
1582
            foreach ($val as $v) {
1583
                $out .= static::RegexForVal($v);
1584
            }
1585
1586
            $out .= ')';
1587
1588
            return $out;
1589
        }
1590
1591
        return
1592
            (
1593
                is_int($val)
1594
                    ? 'int'
1595
                    : (
1596
                        is_bool($val)
1597
                            ? 'bool'
1598
                            : (
1599
                                is_float($val)
1600
                                    ? '(?:float|double)'
1601
                                    : (
1602
                                        is_object($val)
1603
                                            ? ''
1604
                                    : preg_quote(gettype($val), '/')
1605
                                    )
1606
                            )
1607
                    )
1608
            ) .
1609
            (
1610
                ($val instanceof DaftObject\DaftObject)
1611
                    ? (
1612
                        '(?:' .
1613
                            static::RegexForObject(
1614
                                $val
1615
                            ) .
1616
                        ')'
1617
                    )
1618
                :
1619
            preg_quote(
1620
                (
1621
                    '(' .
1622
                    (
1623
                        is_string($val)
1624
                            ? mb_strlen($val, '8bit')
1625
                            : (
1626
                                is_numeric($val)
1627
                                    ? (string) $val
1628
                                    : var_export($val, true)
1629
                            )
1630
                    ) .
1631
                    ')' .
1632
                    (
1633
                        is_string($val)
1634
                            ? (' "' . $val . '"')
1635
                            : ''
1636
                    )
1637
                ),
1638
                '/'
1639
            )
1640
        );
1641
    }
1642
1643
    protected function InvalidImplementations() : array
1644
    {
1645
        return [
1646
            DaftObject\NudgesIncorrectly::class,
1647
            DaftObject\ReadOnlyBad::class,
1648
            DaftObject\ReadOnlyBadDefinesOwnId::class,
1649
            DaftObject\ReadOnlyInsuficientIdProperties::class,
1650
        ];
1651
    }
1652
1653
    protected function FuzzingImplementationsViaArray() : array
1654
    {
1655
        return [
1656
            [
1657
                DaftObject\AbstractTestObject::class,
1658
                [
1659
                    'Foo' => 'Foo',
1660
                    'Bar' => 1.0,
1661
                    'Baz' => 2,
1662
                    'Bat' => true,
1663
                ],
1664
            ],
1665
            [
1666
                DaftObject\AbstractTestObject::class,
1667
                [
1668
                    'Foo' => 'Foo',
1669
                    'Bar' => 2.0,
1670
                    'Baz' => 3,
1671
                    'Bat' => false,
1672
                ],
1673
            ],
1674
            [
1675
                DaftObject\AbstractTestObject::class,
1676
                [
1677
                    'Foo' => 'Foo',
1678
                    'Bar' => 3.0,
1679
                    'Baz' => 4,
1680
                    'Bat' => null,
1681
                ],
1682
            ],
1683
            [
1684
                DaftObject\PasswordHashTestObject::class,
1685
                [
1686
                    'password' => 'foo',
1687
                ],
1688
            ],
1689
            [
1690
                DaftObject\ReadWriteJsonJson::class,
1691
                [
1692
                    'json' => new DaftObject\ReadWriteJson([
1693
                        'Foo' => 'Foo',
1694
                        'Bar' => 1.0,
1695
                        'Baz' => 2,
1696
                        'Bat' => true,
1697
                    ]),
1698
                ],
1699
            ],
1700
            [
1701
                DaftObject\ReadWriteJsonJson::class,
1702
                [
1703
                    'json' => new DaftObject\ReadWriteJson([
1704
                        'Foo' => 'Foo',
1705
                        'Bar' => 2.0,
1706
                        'Baz' => 3,
1707
                        'Bat' => false,
1708
                    ]),
1709
                ],
1710
            ],
1711
            [
1712
                DaftObject\ReadWriteJsonJsonArray::class,
1713
                [
1714
                    'json' => [
1715
                        new DaftObject\ReadWriteJson([
1716
                            'Foo' => 'Foo',
1717
                            'Bar' => 3.0,
1718
                            'Baz' => 4,
1719
                            'Bat' => null,
1720
                        ]),
1721
                        new DaftObject\ReadWriteJson([
1722
                            'Foo' => 'Foo',
1723
                            'Bar' => 1.0,
1724
                            'Baz' => 2,
1725
                            'Bat' => true,
1726
                        ]),
1727
                        new DaftObject\ReadWriteJson([
1728
                            'Foo' => 'Foo',
1729
                            'Bar' => 2.0,
1730
                            'Baz' => 3,
1731
                            'Bat' => false,
1732
                        ]),
1733
                        new DaftObject\ReadWriteJson([
1734
                            'Foo' => 'Foo',
1735
                            'Bar' => 3.0,
1736
                            'Baz' => 4,
1737
                            'Bat' => null,
1738
                        ]),
1739
                    ],
1740
                ],
1741
            ],
1742
        ];
1743
    }
1744
1745
    protected function FuzzingImplementationsViaGenerator() : Generator
1746
    {
1747
        foreach (
1748
            $this->FuzzingImplementationsViaArray() as $args
1749
        ) {
1750
            yield $args;
1751
        }
1752
    }
1753
}
1754