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.

AbstractEntityRepositoryLargeTest   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 374
Duplicated Lines 0 %

Importance

Changes 8
Bugs 2 Features 0
Metric Value
eloc 177
dl 0
loc 374
rs 8.8798
c 8
b 2
f 0
wmc 44

29 Methods

Rating   Name   Duplication   Size   Complexity  
A getClassName() 0 5 1
A matching() 0 13 2
A find() 0 5 1
A itCanBuildADeletionQueryBuilder() 0 5 1
A itCanWorkWithGeneratedAliases() 0 9 1
A getWillThrowAnExceptionIfNothingIsFound() 0 4 1
A addAssocEntities() 0 7 2
A createNamedQuery() 0 7 1
A createQueryBuilder() 0 4 1
A testCount() 0 5 2
A findAll() 0 5 1
A clear() 0 7 1
A setup() 0 12 2
A getRepository() 0 4 1
A getRandomOneBy() 0 15 3
A generateAndSaveTestEntities() 0 8 2
A itCanRunAllTheBasicMethods() 0 13 1
A itCanUseEntitiesInDql() 0 16 1
A sortCollectionById() 0 9 2
A getGetterForType() 0 9 2
A collectionContainsEntity() 0 9 3
A getRandomBy() 0 7 1
A arrayContainsEntity() 0 9 3
A getOneBy() 0 17 1
A findOneBy() 0 18 2
A get() 0 5 1
A getOneByWillThrowAnExceptionIfNothingIsFound() 0 6 1
A createResultSetMappingBuilder() 0 4 1
A findBy() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like AbstractEntityRepositoryLargeTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AbstractEntityRepositoryLargeTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Large\C\Entity\Repositories;
6
7
use Doctrine\Common\Collections\Collection;
8
use Doctrine\Common\Collections\Criteria;
9
use Doctrine\Common\Collections\Expr\Comparison;
10
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
11
use EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories\AbstractEntityRepository;
12
use EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories\RepositoryFactory;
13
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaver;
14
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityDebugDumper;
15
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityGenerator\TestEntityGenerator;
16
use EdmondsCommerce\DoctrineStaticMeta\Entity\Testing\EntityGenerator\TestEntityGeneratorFactory;
17
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
18
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
19
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\AbstractLargeTest;
20
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\AbstractTest;
21
use EdmondsCommerce\DoctrineStaticMeta\Tests\Assets\TestCodeGenerator;
22
use RuntimeException;
23
24
/**
25
 * @see     https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-objects.html#querying
26
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
27
 * @SuppressWarnings(PHPMD.ExcessivePublicCount)
28
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
29
 * @large
30
 * @covers  \EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories\AbstractEntityRepository
31
 */
32
class AbstractEntityRepositoryLargeTest extends AbstractLargeTest
33
{
34
    public const WORK_DIR = AbstractTest::VAR_PATH . '/'
35
                            . self::TEST_TYPE_LARGE . '/AbstractEntityRepositoryLargeTest';
36
37
    private const PERSON_ENTITY_FQN = self::TEST_ENTITIES_ROOT_NAMESPACE . TestCodeGenerator::TEST_ENTITY_PERSON;
38
39
    private const NUM_ENTITIES_QUICK = 2;
40
41
    private const NUM_ENTITIES_FULL = 10;
42
43
    protected static $buildOnce = true;
44
45
    private $generatedEntities = [];
46
    /**
47
     * @var AbstractEntityRepository
48
     */
49
    private $repository;
50
    /**
51
     * @var TestEntityGenerator $entityGenerator
52
     */
53
    private $entityGenerator;
54
55
    private $hasGeneratedEntities = false;
56
57
    public function setup()
58
    {
59
        parent::setUp();
60
        $this->generateTestCode();
61
        $this->setupCopiedWorkDir();
62
        $this->repository      = $this->getRepository();
63
        $this->entityGenerator = $this->container->get(TestEntityGeneratorFactory::class)
64
                                                 ->createForEntityFqn($this->getCopiedFqn(self::PERSON_ENTITY_FQN));
65
        if (false === $this->hasGeneratedEntities) {
66
            $this->createDatabase();
67
            $this->generateAndSaveTestEntities();
68
            $this->hasGeneratedEntities = true;
69
        }
70
    }
71
72
    protected function getRepository(): AbstractEntityRepository
73
    {
74
        return $this->container->get(RepositoryFactory::class)
75
                               ->getRepository($this->getCopiedFqn(self::PERSON_ENTITY_FQN));
76
    }
77
78
    protected function generateAndSaveTestEntities(): void
79
    {
80
        $this->generatedEntities = $this->entityGenerator->generateEntities(
81
            $this->isQuickTests() ? self::NUM_ENTITIES_QUICK : self::NUM_ENTITIES_FULL
82
        );
83
84
        $saver = new EntitySaver($this->getEntityManager());
85
        $saver->saveAll($this->generatedEntities);
86
    }
87
88
    /**
89
     * @test
90
     */
91
    public function itCanRunAllTheBasicMethods(): void
92
    {
93
        $this->find();
94
        $this->get();
95
        $this->findAll();
96
        $this->findBy();
97
        $this->findOneBy();
98
        $this->matching();
99
        $this->createQueryBuilder();
100
        $this->createResultSetMappingBuilder();
101
        $this->get();
102
        $this->getOneBy();
103
        $this->getClassName();
104
    }
105
106
    private function find(): void
107
    {
108
        $expected = $this->generatedEntities[array_rand($this->generatedEntities)];
109
        $actual   = $this->repository->find($expected->getId());
110
        self::assertSame($expected, $actual);
111
    }
112
113
    private function get(): void
114
    {
115
        $expected = $this->generatedEntities[array_rand($this->generatedEntities)];
116
        $actual   = $this->repository->get($expected->getId());
117
        self::assertSame($expected, $actual);
118
    }
119
120
    private function findAll(): void
121
    {
122
        $expected = $this->sortCollectionById($this->generatedEntities);
123
        $actual   = $this->sortCollectionById($this->repository->findAll());
124
        self::assertEquals($expected, $actual);
125
    }
126
127
    private function sortCollectionById(array $collection): array
128
    {
129
        $return = [];
130
        foreach ($collection as $item) {
131
            $return[(string)$item->getId()] = $item;
132
        }
133
        ksort($return);
134
135
        return $return;
136
    }
137
138
    private function findBy(): void
139
    {
140
        $entity = current($this->generatedEntities);
141
        foreach (MappingHelper::COMMON_TYPES as $property) {
142
            $getter   = $this->getGetterForType($property);
143
            $criteria = [$property => $entity->$getter()];
144
            $actual   = $this->repository->findBy($criteria);
145
            self::assertTrue(
146
                $this->arrayContainsEntity($entity, $actual),
147
                'Failed findBy with property ' . $property . ' and entity value' . $entity->$getter()
148
            );
149
        }
150
    }
151
152
    protected function getGetterForType(string $type): string
153
    {
154
        $ucType = ucfirst($type);
155
        $getter = "get$ucType";
156
        if (MappingHelper::TYPE_BOOLEAN === $type) {
157
            $getter = "is$ucType";
158
        }
159
160
        return $getter;
161
    }
162
163
    protected function arrayContainsEntity(EntityInterface $expectedEntity, array $array): bool
164
    {
165
        foreach ($array as $entity) {
166
            if ($entity->getId() === $expectedEntity->getId()) {
167
                return true;
168
            }
169
        }
170
171
        return false;
172
    }
173
174
    private function findOneBy(): void
175
    {
176
        foreach (MappingHelper::COMMON_TYPES as $property) {
177
            $entity   = current($this->generatedEntities);
178
            $getter   = $this->getGetterForType($property);
179
            $value    = $entity->$getter();
180
            $criteria = [
181
                $property => $value,
182
                'id'      => $entity->getId(),
183
            ];
184
            $actual   = $this->repository->findOneBy($criteria);
185
            self::assertEquals(
186
                $entity,
187
                $actual,
188
                'Failed finding one expected entity (ID' . $entity->getId() . ') with $criteria: '
189
                . "\n" . var_export($criteria, true)
190
                . "\n and \$actual: "
191
                . "\n" . (new EntityDebugDumper())->dump($actual, $this->getEntityManager())
0 ignored issues
show
Bug introduced by
It seems like $actual can also be of type null; however, parameter $entity of EdmondsCommerce\Doctrine...tityDebugDumper::dump() does only seem to accept EdmondsCommerce\Doctrine...erfaces\EntityInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

191
                . "\n" . (new EntityDebugDumper())->dump(/** @scrutinizer ignore-type */ $actual, $this->getEntityManager())
Loading history...
192
            );
193
        }
194
    }
195
196
    private function matching(): void
197
    {
198
        foreach (MappingHelper::COMMON_TYPES as $property) {
199
            $entity   = current($this->generatedEntities);
200
            $getter   = $this->getGetterForType($property);
201
            $value    = $entity->$getter();
202
            $criteria = new Criteria();
203
            $criteria->where(new Comparison($property, '=', $value));
204
//            $criteria->andWhere(new Comparison('id', '=', $entity->getId()));
205
            $actual = $this->repository->matching($criteria);
206
            self::assertTrue(
207
                $this->collectionContainsEntity($entity, $actual),
208
                "Failed finding entity by criteria $property = $value"
209
            );
210
        }
211
    }
212
213
    protected function collectionContainsEntity(EntityInterface $expectedEntity, Collection $collection): bool
214
    {
215
        foreach ($collection->getIterator() as $entity) {
216
            if ($entity->getId()->toString() === $expectedEntity->getId()->toString()) {
217
                return true;
218
            }
219
        }
220
221
        return false;
222
    }
223
224
    private function createQueryBuilder(): void
225
    {
226
        $this->repository->createQueryBuilder('foo');
227
        self::assertTrue(true);
228
    }
229
230
    private function createResultSetMappingBuilder(): void
231
    {
232
        $this->repository->createResultSetMappingBuilder('foo');
233
        self::assertTrue(true);
234
    }
235
236
    private function getOneBy(): void
237
    {
238
        $entity   = current($this->generatedEntities);
239
        $getter   = $this->getGetterForType(MappingHelper::TYPE_STRING);
240
        $value    = $entity->$getter();
241
        $criteria = [
242
            MappingHelper::TYPE_STRING => $value,
243
            'id'                       => $entity->getId(),
244
        ];
245
        $actual   = $this->repository->findOneBy($criteria);
246
        self::assertEquals(
247
            $entity,
248
            $actual,
249
            'Failed finding one expected entity (ID' . $entity->getId() . ') with $criteria: '
250
            . "\n" . var_export($criteria, true)
251
            . "\n and \$actual: "
252
            . "\n" . (new EntityDebugDumper())->dump($actual, $this->getEntityManager())
0 ignored issues
show
Bug introduced by
It seems like $actual can also be of type null; however, parameter $entity of EdmondsCommerce\Doctrine...tityDebugDumper::dump() does only seem to accept EdmondsCommerce\Doctrine...erfaces\EntityInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

252
            . "\n" . (new EntityDebugDumper())->dump(/** @scrutinizer ignore-type */ $actual, $this->getEntityManager())
Loading history...
253
        );
254
    }
255
256
    /**
257
     * @test
258
     */
259
    public function getClassName(): void
260
    {
261
        self::assertSame(
262
            ltrim($this->getCopiedFqn(self::PERSON_ENTITY_FQN), '\\'),
263
            $this->repository->getClassName()
264
        );
265
    }
266
267
    /**
268
     * @test
269
     */
270
    public function itCanUseEntitiesInDql(): void
271
    {
272
        $this->addAssocEntities();
273
        $queryBuilder = $this->repository->createQueryBuilder('fetch');
274
        $queryBuilder->where('fetch.attributesAddress IS NOT NULL');
275
276
        $person      = $queryBuilder->getQuery()->execute()[0];
277
        $address     = $person->getAttributesAddress();
278
        $secondQuery = $this->repository->createQueryBuilder('second');
279
        $secondQuery->where('second.attributesAddress = :address');
280
        $secondQuery->setParameter('address', $address);
281
        $query        = $secondQuery->getQuery();
282
        $secondPerson = $query->execute();
283
        self::assertNotEmpty($secondPerson);
284
285
        self::assertSame($address->getId()->toString(), $secondPerson[0]->getAttributesAddress()->getId()->toString());
286
    }
287
288
    private function addAssocEntities(): void
289
    {
290
        foreach ($this->generatedEntities as $entity) {
291
            $this->entityGenerator->addAssociationEntities($entity);
292
        }
293
        $saver = new EntitySaver($this->getEntityManager());
294
        $saver->saveAll($this->generatedEntities);
295
    }
296
297
    /**
298
     * @test
299
     */
300
    public function getWillThrowAnExceptionIfNothingIsFound(): void
301
    {
302
        $this->expectException(DoctrineStaticMetaException::class);
303
        $this->repository->get(time());
304
    }
305
306
    /**
307
     * @test
308
     */
309
    public function getOneByWillThrowAnExceptionIfNothingIsFound(): void
310
    {
311
        $property = MappingHelper::TYPE_STRING;
312
        $criteria = [$property => 'not-a-real-vaule'];
313
        $this->expectException(RuntimeException::class);
314
        $this->repository->getOneBy($criteria);
315
    }
316
317
    /**
318
     * @test
319
     */
320
    public function createNamedQuery(): void
321
    {
322
        $this->markTestIncomplete(
323
            'Need to add a named query for a test entity somehow in the meta data before we can test this'
324
        );
325
        $this->repository->createNamedQuery('foo');
326
        self::assertTrue(true);
327
    }
328
329
    /**
330
     * @test
331
     */
332
    public function clear(): void
333
    {
334
        $this->repository->clear();
335
        $map = $this->getEntityManager()->getUnitOfWork()->getIdentityMap();
336
        self::assertSame(
337
            [],
338
            $map[ltrim($this->getCopiedFqn(self::PERSON_ENTITY_FQN), '\\')]
339
        );
340
    }
341
342
    /**
343
     */
344
    public function testCount(): void
345
    {
346
        self::assertSame(
347
            $this->isQuickTests() ? self::NUM_ENTITIES_QUICK : self::NUM_ENTITIES_FULL,
348
            $this->repository->count([])
349
        );
350
    }
351
352
    /**
353
     * @test
354
     */
355
    public function getRandomBy(): void
356
    {
357
        $criteria = [];
358
        $result   = $this->repository->getRandomBy($criteria);
359
        self::assertCount(1, $result);
360
        $result = $this->repository->getRandomBy($criteria, 2);
361
        self::assertCount(2, $result);
362
    }
363
364
    /**
365
     * @test
366
     */
367
    public function getRandomOneBy(): void
368
    {
369
        $criteria = [];
370
        $tries    = 0;
371
        $maxTries = 10;
372
        while ($tries++ < $maxTries) {
373
            $rand1 = $this->repository->getRandomOneBy($criteria);
374
            $rand2 = $this->repository->getRandomOneBy($criteria);
375
            if ($rand1 !== $rand2) {
376
                self::assertTrue(true);
377
378
                return;
379
            }
380
        }
381
        $this->fail('Failed pulling out two random entities that were not the same');
382
    }
383
384
    /**
385
     * @test
386
     */
387
    public function itCanWorkWithGeneratedAliases(): void
388
    {
389
        $alias = $this->repository->getAlias();
390
        self::assertNotEmpty($alias);
391
        $queryBuilder = $this->repository->createQueryBuilderWithAlias();
392
        $queryBuilder->select($this->repository->aliasPrefix('id'));
393
        $query  = $queryBuilder->getQuery();
394
        $result = $query->getArrayResult();
395
        self::assertNotEmpty($result);
396
    }
397
398
    /**
399
     * @test
400
     */
401
    public function itCanBuildADeletionQueryBuilder(): void
402
    {
403
        $queryBuilder = $this->repository->createDeletionQueryBuilderWithAlias();
404
        $queryBuilder->getQuery()->execute();
405
        self::assertCount(0, $this->repository->findAll());
406
    }
407
}
408