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
Pull Request — master (#78)
by joseph
16:09
created

callEntityGettersAndAssertNotNull()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 34
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
eloc 23
dl 0
loc 34
ccs 0
cts 24
cp 0
rs 8.9297
c 0
b 0
f 0
cc 6
nc 10
nop 1
crap 42
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Testing;
4
5
use Doctrine\Common\Cache\ArrayCache;
6
use Doctrine\Common\Inflector\Inflector;
7
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
8
use Doctrine\ORM\EntityManager;
9
use Doctrine\ORM\Mapping\ClassMetadata;
10
use Doctrine\ORM\Tools\SchemaValidator;
11
use Doctrine\ORM\Utility\PersisterHelper;
12
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\CodeHelper;
13
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
14
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
15
use EdmondsCommerce\DoctrineStaticMeta\Config;
16
use EdmondsCommerce\DoctrineStaticMeta\ConfigInterface;
17
use EdmondsCommerce\DoctrineStaticMeta\Entity\Embeddable\Objects\AbstractEmbeddableObject;
18
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
19
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaver;
20
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaverFactory;
21
use EdmondsCommerce\DoctrineStaticMeta\Entity\Validation\EntityValidatorFactory;
22
use EdmondsCommerce\DoctrineStaticMeta\EntityManager\EntityManagerFactory;
23
use EdmondsCommerce\DoctrineStaticMeta\Exception\ConfigException;
24
use EdmondsCommerce\DoctrineStaticMeta\SimpleEnv;
25
use PHPUnit\Framework\TestCase;
26
use Symfony\Component\Validator\Mapping\Cache\DoctrineCache;
27
28
/**
29
 * Class AbstractEntityTest
30
 *
31
 * This abstract test is designed to give you a good level of test coverage for your entities without any work required.
32
 *
33
 * You should extend the test with methods that test your specific business logic, your validators and anything else.
34
 *
35
 * You can override the methods, properties and constants as you see fit.
36
 *
37
 * @package EdmondsCommerce\DoctrineStaticMeta\Entity
38
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
39
 * @SuppressWarnings(PHPMD.NumberOfChildren)
40
 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
41
 */
42
abstract class AbstractEntityTest extends TestCase implements EntityTestInterface
43
{
44
    /**
45
     * The fully qualified name of the Entity being tested, as calculated by the test class name
46
     *
47
     * @var string
48
     */
49
    protected $testedEntityFqn;
50
51
    /**
52
     * Reflection of the tested entity
53
     *
54
     * @var \ts\Reflection\ReflectionClass
55
     */
56
    protected $testedEntityReflectionClass;
57
58
59
    /**
60
     * @var EntityValidatorFactory
61
     */
62
    protected $entityValidatorFactory;
63
64
    /**
65
     * @var EntityManager
66
     */
67
    protected $entityManager;
68
69
    /**
70
     * @var array
71
     */
72
    protected $schemaErrors = [];
73
74
75
    /**
76
     * @var TestEntityGenerator
77
     */
78
    protected $testEntityGenerator;
79
80
    /**
81
     * @var EntitySaverFactory
82
     */
83
    protected $entitySaverFactory;
84
85
    /**
86
     * @var CodeHelper
87
     */
88
    protected $codeHelper;
89
90
    /**
91
     * @throws ConfigException
92
     * @throws \Exception
93
     * @SuppressWarnings(PHPMD.StaticAccess)
94
     */
95
    protected function setup()
96
    {
97
        $this->getEntityManager(true);
98
        $this->entityValidatorFactory = new EntityValidatorFactory(new DoctrineCache(new ArrayCache()));
99
        $this->entitySaverFactory     = new EntitySaverFactory(
100
            $this->entityManager,
101
            new EntitySaver($this->entityManager),
102
            new NamespaceHelper()
103
        );
104
        $this->testEntityGenerator    = new TestEntityGenerator(
105
            static::SEED,
106
            static::FAKER_DATA_PROVIDERS,
107
            $this->getTestedEntityReflectionClass(),
108
            $this->entitySaverFactory,
109
            $this->entityValidatorFactory
110
        );
111
        $this->codeHelper             = new CodeHelper(new NamespaceHelper());
112
    }
113
114
    /**
115
     * Use Doctrine's standard schema validation to get errors for the whole schema
116
     *
117
     * @param bool $update
118
     *
119
     * @return array
120
     * @throws \Exception
121
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
122
     */
123
    protected function getSchemaErrors(bool $update = false): array
124
    {
125
        if (empty($this->schemaErrors) || true === $update) {
126
            $entityManager      = $this->getEntityManager();
127
            $validator          = new SchemaValidator($entityManager);
128
            $this->schemaErrors = $validator->validateMapping();
129
        }
130
131
        return $this->schemaErrors;
132
    }
133
134
    /**
135
     * If a global function dsmGetEntityManagerFactory is defined, we use this
136
     *
137
     * Otherwise, we use the standard DevEntityManagerFactory,
138
     * we define a DB name which is the main DB from env but with `_test` suffixed
139
     *
140
     * @param bool $new
141
     *
142
     * @return EntityManager
143
     * @throws ConfigException
144
     * @throws \Exception
145
     * @SuppressWarnings(PHPMD)
146
     */
147
    protected function getEntityManager(bool $new = false): EntityManager
148
    {
149
        if (null === $this->entityManager || true === $new) {
150
            if (\function_exists(self::GET_ENTITY_MANAGER_FUNCTION_NAME)) {
151
                $this->entityManager = \call_user_func(self::GET_ENTITY_MANAGER_FUNCTION_NAME);
152
            } else {
153
                SimpleEnv::setEnv(Config::getProjectRootDirectory().'/.env');
154
                $testConfig                                 = $_SERVER;
155
                $testConfig[ConfigInterface::PARAM_DB_NAME] = $_SERVER[ConfigInterface::PARAM_DB_NAME].'_test';
156
                $config                                     = new Config($testConfig);
157
                $this->entityManager                        = (new EntityManagerFactory(new ArrayCache()))
158
                    ->getEntityManager($config);
159
            }
160
        }
161
162
        return $this->entityManager;
163
    }
164
165
166
    /**
167
     * Use Doctrine's built in schema validation tool to catch issues
168
     */
169
    public function testValidateSchema()
170
    {
171
        $errors  = $this->getSchemaErrors();
172
        $class   = $this->getTestedEntityFqn();
173
        $message = '';
174
        if (isset($errors[$class])) {
175
            $message = "Failed ORM Validate Schema:\n";
176
            foreach ($errors[$class] as $err) {
177
                $message .= "\n * $err \n";
178
            }
179
        }
180
        self::assertEmpty($message);
181
    }
182
183
184
    /**
185
     * @param string        $class
186
     * @param int|string    $id
187
     * @param EntityManager $entityManager
188
     *
189
     * @return EntityInterface|null
190
     */
191
    protected function loadEntity(string $class, $id, EntityManager $entityManager): ?EntityInterface
192
    {
193
        return $entityManager->getRepository($class)->find($id);
194
    }
195
196
    public function testConstructor(): EntityInterface
197
    {
198
        $class  = $this->getTestedEntityFqn();
199
        $entity = new $class($this->entityValidatorFactory);
200
        self::assertInstanceOf($class, $entity);
201
202
        return $entity;
203
    }
204
205
    /**
206
     * @param EntityInterface $entity
207
     *
208
     * @throws ConfigException
209
     * @throws \Doctrine\ORM\Query\QueryException
210
     * @throws \ReflectionException
211
     * @depends testConstructor
212
     */
213
    public function testGetDefaults(EntityInterface $entity)
214
    {
215
        $this->callEntityGettersAndAssertNotNull($entity);
216
    }
217
218
    /**
219
     * Loop through Entity fields, call the getter and where possible assert there is a value returned
220
     *
221
     * @param EntityInterface $entity
222
     *
223
     * @throws ConfigException
224
     * @throws \Doctrine\ORM\Query\QueryException
225
     * @throws \ReflectionException
226
     * @SuppressWarnings(PHPMD.StaticAccess)
227
     */
228
    protected function callEntityGettersAndAssertNotNull(EntityInterface $entity): void
229
    {
230
        $class         = $this->getTestedEntityFqn();
231
        $entityManager = $this->getEntityManager();
232
        $meta          = $entityManager->getClassMetadata($class);
233
        foreach ($meta->getFieldNames() as $fieldName) {
234
            $type   = PersisterHelper::getTypeOfField($fieldName, $meta, $entityManager)[0];
235
            $method = $this->getGetterNameForField($fieldName, $type);
236
            if (\ts\stringContains($method, '.')) {
237
                list($getEmbeddableMethod,) = explode('.', $method);
238
                $embeddable = $entity->$getEmbeddableMethod();
239
                self::assertInstanceOf(AbstractEmbeddableObject::class, $embeddable);
240
                continue;
241
            }
242
            $reflectionMethod = new \ReflectionMethod($entity, $method);
243
            if ($reflectionMethod->hasReturnType()) {
244
                $returnType = $reflectionMethod->getReturnType();
245
                $allowsNull = $returnType->allowsNull();
246
                if ($allowsNull) {
247
                    // As we can't assert anything here so simply call
248
                    // the method and allow the type hint to raise any
249
                    // errors.
250
                    $entity->$method();
251
                    continue;
252
                }
253
                self::assertNotNull($entity->$method(), "$fieldName getter returned null");
254
                continue;
255
            }
256
            // If there is no return type then we can't assert anything,
257
            // but again we can just call the getter to check for errors
258
            $entity->$method();
259
        }
260
        if (0 === $this->getCount()) {
261
            self::markTestSkipped('No assertable getters in this Entity');
262
        }
263
    }
264
265
    /**
266
     * Generate a new entity and then update our Entity with the values from the generated one
267
     *
268
     * @param EntityInterface $entity
269
     *
270
     * @throws ConfigException
271
     * @throws \Doctrine\ORM\Mapping\MappingException
272
     * @throws \Doctrine\ORM\Query\QueryException
273
     * @throws \ReflectionException
274
     * @SuppressWarnings(PHPMD.StaticAccess)
275
     */
276
    protected function updateEntityFields(EntityInterface $entity): void
277
    {
278
        $class         = $this->getTestedEntityFqn();
279
        $entityManager = $this->getEntityManager();
280
        $meta          = $entityManager->getClassMetadata($class);
281
        $entityManager = $this->getEntityManager();
282
        $class         = $this->getTestedEntityFqn();
283
        $generated     = $this->testEntityGenerator->generateEntity($entityManager, $class, 10);
284
        $identifiers   = \array_flip($meta->getIdentifier());
285
        foreach ($meta->getFieldNames() as $fieldName) {
286
            if (isset($identifiers[$fieldName])) {
287
                continue;
288
            }
289
            if (true === $this->isUniqueField($meta, $fieldName)) {
290
                continue;
291
            }
292
            $setter = 'set'.$fieldName;
293
            if (!\method_exists($entity, $setter)) {
294
                continue;
295
            }
296
            $type   = PersisterHelper::getTypeOfField($fieldName, $meta, $entityManager)[0];
297
            $getter = $this->getGetterNameForField($fieldName, $type);
298
            if (\ts\stringContains($getter, '.')) {
299
                list($getEmbeddableMethod, $fieldInEmbeddable) = explode('.', $getter);
300
                $getterInEmbeddable  = 'get'.$fieldInEmbeddable;
301
                $setterInEmbeddable  = 'set'.$fieldInEmbeddable;
302
                $generatedEmbeddable = $generated->$getEmbeddableMethod();
303
                $embeddable          = $entity->$getEmbeddableMethod();
304
                if (
305
                    \method_exists($embeddable, $setterInEmbeddable)
306
                    && \method_exists($embeddable, $getterInEmbeddable)
307
                ) {
308
                    $embeddable->$setterInEmbeddable($generatedEmbeddable->$getterInEmbeddable());
309
                }
310
                continue;
311
            }
312
            $entity->$setter($generated->$getter());
313
        }
314
    }
315
316
    protected function isUniqueField(ClassMetadata $meta, string $fieldName): bool
317
    {
318
        $fieldMapping = $meta->getFieldMapping($fieldName);
319
        if (array_key_exists('unique', $fieldMapping) && true === $fieldMapping['unique']) {
320
            return true;
321
        }
322
323
        return false;
324
    }
325
326
    /**
327
     * Test that we have correctly generated an instance of our test entity
328
     *
329
     * @throws ConfigException
330
     * @throws \Doctrine\ORM\Query\QueryException
331
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
332
     * @throws \Exception
333
     * @throws \ReflectionException
334
     * @SuppressWarnings(PHPMD.StaticAccess)
335
     */
336
    public function testGeneratedCreate(): EntityInterface
337
    {
338
        $entityManager = $this->getEntityManager();
339
        $class         = $this->getTestedEntityFqn();
340
        $generated     = $this->testEntityGenerator->generateEntity($entityManager, $class);
341
        self::assertInstanceOf($class, $generated);
342
        $this->testEntityGenerator->addAssociationEntities($entityManager, $generated);
343
        $this->validateEntity($generated);
344
        $this->callEntityGettersAndAssertNotNull($generated);
345
        $this->entitySaverFactory->getSaverForEntity($generated)->save($generated);
346
347
        return $generated;
348
    }
349
350
    /**
351
     * Test that we can load the entity and then get and set
352
     *
353
     * @param EntityInterface $entity
354
     *
355
     * @return EntityInterface|null
356
     * @throws ConfigException
357
     * @throws \Doctrine\ORM\Mapping\MappingException
358
     * @throws \Doctrine\ORM\Query\QueryException
359
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
360
     * @throws \ReflectionException
361
     * @depends testGeneratedCreate
362
     */
363
    public function testLoadedEntity(EntityInterface $entity): EntityInterface
364
    {
365
        $class         = $this->getTestedEntityFqn();
366
        $entityManager = $this->getEntityManager();
367
        $loaded        = $this->loadEntity($class, $entity->getId(), $entityManager);
368
        self::assertSame($entity->getId(), $loaded->getId());
369
        self::assertInstanceOf($class, $loaded);
370
        $this->updateEntityFields($loaded);
371
        $this->assertAllAssociationsAreNotEmpty($loaded);
372
        $this->validateEntity($loaded);
373
        $this->removeAllAssociations($loaded);
374
        $this->assertAllAssociationsAreEmpty($loaded);
375
        $this->entitySaverFactory->getSaverForEntity($loaded)->save($loaded);
376
377
        return $loaded;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $loaded could return the type null which is incompatible with the type-hinted return EdmondsCommerce\Doctrine...erfaces\EntityInterface. Consider adding an additional type-check to rule them out.
Loading history...
378
    }
379
380
    /**
381
     * @param EntityInterface $entity
382
     *
383
     * @throws ConfigException
384
     * @depends testLoadedEntity
385
     */
386
    public function testReloadedEntityHasNoAssociations(EntityInterface $entity): void
387
    {
388
        $class         = $this->getTestedEntityFqn();
389
        $entityManager = $this->getEntityManager();
390
        $reLoaded      = $this->loadEntity($class, $entity->getId(), $entityManager);
391
        self::assertEquals($entity->__toString(), $reLoaded->__toString());
392
        $this->assertAllAssociationsAreEmpty($reLoaded);
393
    }
394
395
    protected function assertAllAssociationsAreNotEmpty(EntityInterface $entity)
396
    {
397
        $entityManager = $this->getEntityManager();
398
        $class         = $this->getTestedEntityFqn();
399
        $meta          = $entityManager->getClassMetadata($class);
400
        foreach ($meta->getAssociationMappings() as $mapping) {
401
            $getter = 'get'.$mapping['fieldName'];
402
            if ($meta->isCollectionValuedAssociation($mapping['fieldName'])) {
403
                $collection = $entity->$getter()->toArray();
404
                self::assertNotEmpty(
405
                    $collection,
406
                    'Failed to load the collection of the associated entity ['.$mapping['fieldName']
407
                    .'] from the generated '.$class
408
                    .', make sure you have reciprocal adding of the association'
409
                );
410
                self::assertCorrectMappings($class, $mapping, $entityManager);
0 ignored issues
show
Bug Best Practice introduced by
The method EdmondsCommerce\Doctrine...assertCorrectMappings() is not static, but was called statically. ( Ignorable by Annotation )

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

410
                self::/** @scrutinizer ignore-call */ 
411
                      assertCorrectMappings($class, $mapping, $entityManager);
Loading history...
411
                continue;
412
            }
413
            $association = $entity->$getter();
414
            self::assertNotEmpty(
415
                $association,
416
                'Failed to load the associated entity: ['.$mapping['fieldName']
417
                .'] from the generated '.$class
418
            );
419
            self::assertNotEmpty(
420
                $association->getId(),
421
                'Failed to get the ID of the associated entity: ['.$mapping['fieldName']
422
                .'] from the generated '.$class
423
            );
424
        }
425
    }
426
427
    /**
428
     * @param EntityInterface $entity
429
     *
430
     * @throws ConfigException
431
     * @SuppressWarnings(PHPMD.StaticAccess)
432
     */
433
    protected function removeAllAssociations(EntityInterface $entity)
434
    {
435
        $entityManager = $this->getEntityManager();
436
        $class         = $this->getTestedEntityFqn();
437
        $meta          = $entityManager->getClassMetadata($class);
438
        foreach ($meta->getAssociationMappings() as $mapping) {
439
            $remover = 'remove'.Inflector::singularize($mapping['fieldName']);
440
            if ($meta->isCollectionValuedAssociation($mapping['fieldName'])) {
441
                $getter    = 'get'.$mapping['fieldName'];
442
                $relations = $entity->$getter();
443
                foreach ($relations as $relation) {
444
                    $entity->$remover($relation);
445
                }
446
                continue;
447
            }
448
            $entity->$remover();
449
        }
450
        $this->assertAllAssociationsAreEmpty($entity);
451
    }
452
453
    protected function assertAllAssociationsAreEmpty(EntityInterface $entity)
454
    {
455
        $entityManager = $this->getEntityManager();
456
        $class         = $this->getTestedEntityFqn();
457
        $meta          = $entityManager->getClassMetadata($class);
458
        foreach ($meta->getAssociationMappings() as $mapping) {
459
            $getter = 'get'.$mapping['fieldName'];
460
            if ($meta->isCollectionValuedAssociation($mapping['fieldName'])) {
461
                $collection = $entity->$getter()->toArray();
462
                self::assertEmpty(
463
                    $collection,
464
                    'Collection of the associated entity ['.$mapping['fieldName']
465
                    .'] is not empty after calling remove'
466
                );
467
                continue;
468
            }
469
            $association = $entity->$getter();
470
            self::assertEmpty(
471
                $association,
472
                'Failed to remove associated entity: ['.$mapping['fieldName']
473
                .'] from the generated '.$class
474
            );
475
        }
476
    }
477
478
479
    /**
480
     * @depends testConstructor
481
     *
482
     * @param EntityInterface $entity
483
     */
484
    public function testGetGetters(EntityInterface $entity)
485
    {
486
        $getters = $entity->getGetters();
487
        self::assertNotEmpty($getters);
488
        foreach ($getters as $getter) {
489
            self::assertRegExp('%^(get|is|has).+%', $getter);
490
        }
491
    }
492
493
    /**
494
     * @depends testConstructor
495
     *
496
     * @param EntityInterface $entity
497
     */
498
    public function testSetSetters(EntityInterface $entity)
499
    {
500
        $setters = $entity->getSetters();
501
        self::assertNotEmpty($setters);
502
        foreach ($setters as $setter) {
503
            self::assertRegExp('%^(set|add).+%', $setter);
504
        }
505
    }
506
507
508
    protected function getGetterNameForField(string $fieldName, string $type): string
509
    {
510
        if ($type === 'boolean') {
511
            return $this->codeHelper->getGetterMethodNameForBoolean($fieldName);
512
        }
513
514
        return 'get'.$fieldName;
515
    }
516
517
    /**
518
     * Loop through entity fields and find unique ones
519
     *
520
     * Then ensure that the unique rule is being enforced as expected
521
     *
522
     * @throws ConfigException
523
     * @throws \Doctrine\ORM\Mapping\MappingException
524
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
525
     * @throws \ReflectionException
526
     * @throws \Doctrine\ORM\Mapping\MappingException
527
     */
528
    public function testUniqueFieldsMustBeUnique(): void
529
    {
530
        $class         = $this->getTestedEntityFqn();
531
        $entityManager = $this->getEntityManager();
532
        $meta          = $entityManager->getClassMetadata($class);
533
        $uniqueFields  = [];
534
        foreach ($meta->getFieldNames() as $fieldName) {
535
            if (true === $this->isUniqueField($meta, $fieldName)) {
536
                $uniqueFields[] = $fieldName;
537
            }
538
        }
539
        if ([] === $uniqueFields) {
540
            self::markTestSkipped('No unique fields to check');
541
542
            return;
543
        }
544
        foreach ($uniqueFields as $fieldName) {
545
            $primary      = $this->testEntityGenerator->generateEntity($entityManager, $class);
546
            $secondary    = $this->testEntityGenerator->generateEntity($entityManager, $class);
547
            $getter       = 'get'.$fieldName;
548
            $setter       = 'set'.$fieldName;
549
            $primaryValue = $primary->$getter();
550
            $secondary->$setter($primaryValue);
551
            $saver = $this->entitySaverFactory->getSaverForEntity($primary);
552
            $this->expectException(UniqueConstraintViolationException::class);
553
            $saver->saveAll([$primary, $secondary]);
554
        }
555
    }
556
557
    /**
558
     * Check the mapping of our class and the associated entity to make sure it's configured properly on both sides.
559
     * Very easy to get wrong. This is in addition to the standard Schema Validation
560
     *
561
     * @param string        $classFqn
562
     * @param array         $mapping
563
     * @param EntityManager $entityManager
564
     */
565
    protected function assertCorrectMappings(string $classFqn, array $mapping, EntityManager $entityManager)
566
    {
567
        $pass                                 = false;
568
        $associationFqn                       = $mapping['targetEntity'];
569
        $associationMeta                      = $entityManager->getClassMetadata($associationFqn);
570
        $classTraits                          = $entityManager->getClassMetadata($classFqn)
571
                                                              ->getReflectionClass()
572
                                                              ->getTraits();
573
        $unidirectionalTraitShortNamePrefixes = [
574
            'Has'.$associationFqn::getSingular().RelationsGenerator::PREFIX_UNIDIRECTIONAL,
575
            'Has'.$associationFqn::getPlural().RelationsGenerator::PREFIX_UNIDIRECTIONAL,
576
        ];
577
        foreach ($classTraits as $trait) {
578
            foreach ($unidirectionalTraitShortNamePrefixes as $namePrefix) {
579
                if (0 === \stripos($trait->getShortName(), $namePrefix)) {
580
                    return;
581
                }
582
            }
583
        }
584
        foreach ($associationMeta->getAssociationMappings() as $associationMapping) {
585
            if ($classFqn === $associationMapping['targetEntity']) {
586
                $pass = self::assertCorrectMapping($mapping, $associationMapping, $classFqn);
0 ignored issues
show
Bug Best Practice introduced by
The method EdmondsCommerce\Doctrine...:assertCorrectMapping() is not static, but was called statically. ( Ignorable by Annotation )

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

586
                /** @scrutinizer ignore-call */ 
587
                $pass = self::assertCorrectMapping($mapping, $associationMapping, $classFqn);
Loading history...
587
                break;
588
            }
589
        }
590
        self::assertTrue($pass, 'Failed finding association mapping to test for '."\n".$mapping['targetEntity']);
591
    }
592
593
    /**
594
     * @param array  $mapping
595
     * @param array  $associationMapping
596
     * @param string $classFqn
597
     *
598
     * @return bool
599
     */
600
    protected function assertCorrectMapping(array $mapping, array $associationMapping, string $classFqn): bool
601
    {
602
        if (empty($mapping['joinTable'])) {
603
            self::assertArrayNotHasKey(
604
                'joinTable',
605
                $associationMapping,
606
                $classFqn.' join table is empty,
607
                        but association '.$mapping['targetEntity'].' join table is not empty'
608
            );
609
610
            return true;
611
        }
612
        self::assertNotEmpty(
613
            $associationMapping['joinTable'],
614
            "$classFqn joinTable is set to ".$mapping['joinTable']['name']
615
            ." \n association ".$mapping['targetEntity'].' join table is empty'
616
        );
617
        self::assertSame(
618
            $mapping['joinTable']['name'],
619
            $associationMapping['joinTable']['name'],
620
            "join tables not the same: \n * $classFqn = ".$mapping['joinTable']['name']
621
            ." \n * association ".$mapping['targetEntity']
622
            .' = '.$associationMapping['joinTable']['name']
623
        );
624
        self::assertArrayHasKey(
625
            'inverseJoinColumns',
626
            $associationMapping['joinTable'],
627
            "join table join columns not the same: \n * $classFqn joinColumn = "
628
            .$mapping['joinTable']['joinColumns'][0]['name']
629
            ." \n * association ".$mapping['targetEntity']
630
            .' inverseJoinColumn is not set'
631
        );
632
        self::assertSame(
633
            $mapping['joinTable']['joinColumns'][0]['name'],
634
            $associationMapping['joinTable']['inverseJoinColumns'][0]['name'],
635
            "join table join columns not the same: \n * $classFqn joinColumn = "
636
            .$mapping['joinTable']['joinColumns'][0]['name']
637
            ." \n * association ".$mapping['targetEntity']
638
            .' inverseJoinColumn = '.$associationMapping['joinTable']['inverseJoinColumns'][0]['name']
639
        );
640
        self::assertSame(
641
            $mapping['joinTable']['inverseJoinColumns'][0]['name'],
642
            $associationMapping['joinTable']['joinColumns'][0]['name'],
643
            "join table join columns  not the same: \n * $classFqn inverseJoinColumn = "
644
            .$mapping['joinTable']['inverseJoinColumns'][0]['name']
645
            ." \n * association ".$mapping['targetEntity'].' joinColumn = '
646
            .$associationMapping['joinTable']['joinColumns'][0]['name']
647
        );
648
649
        return true;
650
    }
651
652
653
    protected function validateEntity(EntityInterface $entity): void
654
    {
655
        $entity->validate();
656
    }
657
658
659
    /**
660
     * Get the fully qualified name of the Entity we are testing,
661
     * assumes EntityNameTest as the entity class short name
662
     *
663
     * @return string
664
     */
665
    protected function getTestedEntityFqn(): string
666
    {
667
        if (null === $this->testedEntityFqn) {
668
            $this->testedEntityFqn = \substr(static::class, 0, -4);
669
        }
670
671
        return $this->testedEntityFqn;
672
    }
673
674
675
    /**
676
     * Get a \ReflectionClass for the currently tested Entity
677
     *
678
     * @return \ts\Reflection\ReflectionClass
679
     * @throws \ReflectionException
680
     */
681
    protected function getTestedEntityReflectionClass(): \ts\Reflection\ReflectionClass
682
    {
683
        if (null === $this->testedEntityReflectionClass) {
684
            $this->testedEntityReflectionClass = new \ts\Reflection\ReflectionClass(
685
                $this->getTestedEntityFqn()
686
            );
687
        }
688
689
        return $this->testedEntityReflectionClass;
690
    }
691
}
692